I have the following
protocol FooPresentable {
var bar: BarPresentable { get }
}
protocol BarPresentable {
}
class Foo {
let bar: Bar
}
extension Bar: BarPresentable {
}
extension Foo: FooPresentable {
}
And I get the error Foo
does not conform to FooPresentable
. Is it possible to have Foo
conform to FooPresentable
by just letting the compiler know that all Bar
s conform to BarPresentable
CodePudding user response:
protocol FooPresentable {
var bar: BarPresentable { get }
}
For Foo
to conform to FooPresentable
, the type of it’s bar
property must be BarPresentable
, which is not the same as having a bar
property whose type conforms to BarPresentable
. The type BarPresentable
represents any type that conforms to BarPresentable
:
struct Bar: BarPresentable {}
struct Baz: BarPresentable {}
let aBarPresentable: BarPresentable = Bar()
aBarPresentable = Baz()
What you probably want instead is an associated type:
protocol FooPresentable {
associatedtype BarBarPresentable: BarPresentable
var bar: BarBarPresentable { get }
}
This means that a type A
conforming to FooPresentable
must have a property bar
which has a type (TheBarPresentable
) specific to A
that conforms to BarPresentable
. I think this is best explained with an example:
class Foo {
let bar: Bar
init(bar: Bar) { self.bar = bar }
}
extension Foo: FooPresentable {
typealias BarBarPresentable = Bar
}
In fact, you don’t need the explicit typealias
declaration as Swift can infer this for you:
extension Foo: FooPresentable {}
CodePudding user response:
Not the way you're doing it, no. You've written a protocol that says: to conform to me, declare a variable bar
that is actually declared as BarPresentable. Your Foo doesn't do that; it declares a variable bar
that is declared as being Bar, which is not the same thing.
What you want is a generic protocol where the generic is constrained to be an adopter of BarPresentable.
Here is a complete example that compiles:
protocol FooPresentable {
// this says: `bar` must be declared as a type that adopts BarPresentable
associatedtype T: BarPresentable
var bar: T { get }
}
protocol BarPresentable {
}
struct Bar {}
struct Foo {
// behold, `bar` _is_ declared as a type that adopts BarPresentable
let bar: Bar
}
extension Bar: BarPresentable {
}
extension Foo: FooPresentable {
}
CodePudding user response:
FooPresentable
has an associated type.
protocol FooPresentable {
associatedtype Bar: BarPresentable
var bar: Bar { get }
}
class Foo {
let bar: Module.Bar = .init()
}
CodePudding user response:
You have to use existential types or associatedtype
protocol FooPresentable {
associatedtype B : BarPresentable
var bar: B { get }
}
Or
protocol FooPresentable {
var bar: any BarPresentable { get }
}
Which is correct depends on your actual use case.