问题
I don't understand why this doesn't compile. It does if I remove the where
restriction from the P
type.
import Combine
protocol Foo {
associatedtype P: Publisher where P.Output == Int
var publisher: P { get }
}
struct Bar: Foo {
var publisher: some Publisher {
Just(1)
}
}
The error says that Type 'Bar' does not conform to protocol 'Foo'
. I guess it's because publisher
return type is not just any some Publisher
. But in SwiftUI, the View
uses a similar approach, just that it doesn't have restrictions over the View
type.
Is there any way I can make this code to compile?
回答1:
The reason why it doesn't compile is because some Publisher
declares an opaque type, but the protocol requires that the type must be "see-through".
some Publisher
is "opaque" in the sense that callers cannot see exactly what type the property actually is, and can only know that it conforms to Publisher
. This directly contradicts with the protocol requirement that P.Output
has to be Int
. To check P.Output
is Int
, you have to "see through" some Publisher
, but you can't.
Since the compiler can't check the publisher's Output
, it can't check whether your type really conforms to the protocol or not. Therefore it chooses the "safe route" concludes that your type does not conform to the protocol.
I think you should use the AnyPublisher
type eraser:
var publisher: AnyPublisher<Int, Never> {
Just(1).eraseToAnyPublisher()
}
SwiftUI's View
protocol does not have this problem because it does not require Body
to be "see-through". It just requires that Body
is a conformer of View
, which some View
, by definition, is.
来源:https://stackoverflow.com/questions/63821754/some-protocol-causes-type-to-not-conform-to-protocol