Reputation: 18729
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
?
Upvotes: 1
Views: 174
Reputation: 5094
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()
}
Upvotes: 1
Reputation: 119380
=
:var someOther: String { "something else" }
var
:var someValue: SomethingProtocol = SomethingConcret()
var
. You may want to cast it first:var otherValue: String? { (someValue as? SomethingConcret)?.someOther
protocol SomethingProtocol {
var something: String { get }
}
class SomethingConcrete: SomethingProtocol {
var something: String { "something" }
var someOther: String { "something else" }
}
protocol EntityProtocol {
var someValue: SomethingProtocol { get }
}
class ConcreteEntity: EntityProtocol {
var someValue: SomethingProtocol = SomethingConcrete()
var otherValue: String? { (someValue as? SomethingConcrete)?.someOther }
}
Upvotes: 0