我已经重命名了你的标识符,所以我可以考虑它们:
protocol P {
typealias E : C<Self>
}
class A : P {
typealias E = C1<Any>
}
class B : P {
typealias E = C2<Any>
}
class C<T> {}
class C1<T> : C<A> {}
class S<T, U : P> : C<T> {} // <-- mark!
class C2<T> : S<B, A> {}
这应该最终并且几乎可以解决。实际上,您想要的是:
class B : P {
typealias E = C<B> // which is what P requires (same with class A)
}
但是,在您定义的标记行上,您class S
要求编译器检查类型,U : P
然后B
作为要检查的具体类型传递。不幸的是,此时B
' 的一致性P
仍未解决(即它本身是根据 定义的C2 : S : C
,这就是你要使用的地方U : P
)。删除: P
inU : P
会删除错误,尽管这可能不是您想要的。再说一次,根据您的需要,可能有任意数量的解决方案:)
编辑
以下是对@igul222 大大简化的代码示例的回应。但是,我仍然认为,编译器只是返回一个不太有用的错误消息,这实际上是由递归类型定义引起的。例如,如果您enum
根据自身定义 an:
enum E {
case C(E) // error: recursive value type 'E' is not allowed
}
现在,这可能也是以下问题:
class C<T> {}
protocol P {
typealias E : C<Self>
var c: E { get }
}
final class A : P {
typealias E = C<A>
var c: E { return E() }
}
// --> error: type 'A' does not conform to protocol 'P'
// --> note: protocol requires property 'c' with type 'E'
// --> note: candidate has non-matching type 'E'
...这也不起作用(您的要点的一个版本):
class C<T> {}
protocol P {
typealias E : C<Self>
}
final class A : P {
typealias E = C<A>
}
class X<U : P> {}
X<A>() // --> error: type 'E' does not inherit from 'C<`Self`>'
... 或这个:
class C<T> {}
protocol P {
typealias E : C<Self>
}
final class A : P {
typealias E = C<A>
}
let a = A()
func f<T: P>(T) {}
f(a) // --> error: 'A' is not identical to '`Self`'
编译器似乎在说的是 Self
in C<Self>
is not yet A
,即那A
还不是它,Self
因为A
它必须符合P
which 依次等待C<Self>
检出...但是以下工作因为A
不再定义关联类型本身:
class C<T> {}
protocol P {
var c: C<Self> { get }
}
final class A : P {
typealias E = C<A> // just a typealias, no longer an associated type
var c: E { return E() }
}
一些函数式编程模式需要递归定义的类型,所以在 Swift 中使用它可能会很好。但是,目前,我不确定是否可以有效地遵循具有 form 关联类型的协议T<Self>
,即使编译器允许其定义......否则,这一切都应该在运行时工作。
编辑 2
我刚刚升级到Xcode 6.1 GM Seed,情况发生了变化!以下片段,以前不会编译,现在编译并且运行良好!
protocol A {
var b: B? { get set }
}
protocol B {
var a: A? { get set }
}
class Ca: A {
var b: B?
}
class Cb: B {
var a: A?
}
let a = Ca() // --> {nil}
let b = Cb() // --> {nil}
a.b = b // --> {{{...}}}
b.a = a // --> {{{...}}}
然而,这种改进并没有扩展到递归定义的关联类型。