Search code examples
swiftprotocols

Is it possible to implement a protocol type variable with a concrete class in Swift?


Is it possible to implement a protocol type var with a concrete class which implements this protocol?

Does that sound confusing? Here is an example :-)

// A protocol requires some var. And an implementation of this class
protocol SomethingProtocol {
    var something: String { get }
}

class SomethingConcrete: SomethingProtocol {
    var something: String { "something" }
    var someOther: String { "something else" }
}


// A protocol which requires someValue of protocol type SomethingProtocol
protocol EntityProtocol {
    var someValue: SomethingProtocol { get }
}


// Implementation of EntityProtocol
class ConcreteEntiy: EntityProtocol {
    // DOES NOT WORK:
    // Implementing the var someValue of required typ SomethingProtocol
    // using its implementation SomethingConcret 
    //       
    // Error: Type 'ConcretEntiy' does not conform to protocol 'EntityProtocol'
    var someValue: SomethingConcrete = SomethingConcrete()



    // DOES WORK:
    // Implementation as SomethingProtocol as required by EntityProtocol
    // but no access to others values of SomethingConcret
    var someValue: SomethingProtocol = SomethingConcrete()
    
    
    // Error: Value of type 'SomethingProtocol' has no member 'somethingElse'
    let otherValue = someValue.somethingElse
}
  • EntityProtocol requires a var someValue of protocol type SomethingProtocol
  • SomethingConcrete implements SomethingProtocol and thus is of type SomethingProtocol
  • ConcreteClass implements EntityProtocol and thus needs a var someValue of protocol type SomethingProtocol

Why is it not possible to full fill the requirement of EntityProtocol by providing a var someValue of type SomethingConcrete?


Solution

  • You're requiring the class conforming to EntityProtocol to have a property holding SomethingProtocol, & not any object conforming to that protocol.

    That's why generics exist, when using associatedtype you're first implementation works because you're setting the type of someValue to be whatever you say it is that conforms to SomethingProtocol(i.e: SomethingConcret). Hence it's not set like your attempt, it is inferred.

    // A protocol requires some var. And an implementation of this class
    protocol SomethingProtocol {
        var something: String { get }
    }
    
    class SomethingConcret: SomethingProtocol {
        var something: String { "something" }
        var someOther: String { "something else" }
    }
    
    
    // A protocol which requires someValue conforming to the type SomethingProtocol
    protocol EntityProtocol {
        associatedtype SomeValue: SomethingProtocol
        var someValue: SomeValue { get }
    }
    
    
    // Implementation of EntityProtocol
    class ConcretEntiy: EntityProtocol {
        // WORKS:
        // Implementing the var someValue of required type SomethingProtocol
        // using its implementation SomethingConcret
       // has access to others values of SomethingConcret
        var someValue: SomethingConcret = SomethingConcret()
    
    
    
        // ALSO WORKS:
        // Implementation as SomethingProtocol as required by EntityProtocol
        // but no access to others values of SomethingConcret
        var someValue: SomethingProtocol = SomethingConcret()
    }