Reputation: 2353
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
Upvotes: 0
Views: 62
Reputation: 535989
Is it possible to have Foo conform to FooPresentable by just letting the compiler know that all Bars conform to BarPresentable
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 {
}
Upvotes: 2
Reputation: 14148
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 {}
Upvotes: 2
Reputation: 29676
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.
Check out Design protocol interfaces in Swift
Upvotes: 0
Reputation:
FooPresentable
has an associated type.
protocol FooPresentable {
associatedtype Bar: BarPresentable
var bar: Bar { get }
}
class Foo {
let bar: Module.Bar = .init()
}
Upvotes: 0