The problem is that T
in this case is "some type that conforms to NonFunkyProtocol
". weeProp
is also "something that conforms to NonFunkyProtocol
" but there's nothing that says that weeProp
is of type T
.
Consider the following case:
extension Int: NonFunkyProtocol {}
extension String: NonFunkyProtocol {}
Both Int and String conform.
Now I construct a WeeStruct with a String:
let wee = WeeStruct(weeProp: "")
And I call funky
with a function that requires an Int (since Int a conforming type, it can be T
):
wee.funky { (int: Int) -> Void in print(int + 1) }
So this would pass ""
to the closure. How can that work?
So you either need to require the closure handle any NonFunkyProtocol
(I strongly suspect this is what you mean):
func funky(_ closure: (NonFunkyProtocol) -> Void)
Or you need to nail down weeProp
to T
by making T
an associatedtype:
protocol FunkyProtocol {
associatedtype T: NonFunkyProtocol
func funky(_ closure: (T) -> Void)
}
struct WeeStruct<T:NonFunkyProtocol>: FunkyProtocol {
let weeProp: T
func funky(_ closure: (T) -> Void) {
closure(weeProp)
}
}
I would be very careful before adding an associatedtype, though. That completely changes the nature of FunkyProtocol.
If FunkyProtocol really is just this one requirement, you should also ask what it's solving versus just a function. Why pass around WeeStruct
with all its protocol baggage, when you could just use the wee.funky
function directly? Are there protocol extension on FunkyProtocol? If you can't write generic algorithms against FunkyProtocol, it probably should't be a protocol.