类型X不继承自Y [英] Type X does not inherit from Y
问题描述
以下Swift代码在最后一行产生此错误:Type 'E' does not inherit from 'C<Self>'
.不知道这是怎么回事.任何线索将不胜感激.
The following Swift code yields this error on the last line: Type 'E' does not inherit from 'C<Self>'
. Not sure what's going on here. Any clues would be appreciated.
class C<T> {}
protocol P {
typealias E : C<Self>
}
class A : P {
typealias E = C<A>
}
class S<U : P> {}
class C2<T> : S<A> {}
更新:我简化了破碎的示例.可以在此问题的编辑历史记录中找到旧版本(milos的答案所指).
Update: I simplified the broken example. The old version (to which milos' answer refers) can be found in this question's edit history.
推荐答案
我已经重命名了您的标识符,以便我考虑一下:
I have renamed your identifiers so I can think about them:
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> {}
这应该最终并且几乎可以解决.实际上,您想要的是:
This should eventually, and very nearly does, work out. In effect, what you want is:
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
的地方).删除U : P
中的: P
会删除该错误,尽管这可能不是您想要的.再根据您想要的内容,可能有许多解决方案:)
However, on the marked line, where you are defining class S
you are asking the compiler to check the type of U : P
and then pass B
as the concrete type to check. Unfortunately, at this point B
's conformance to P
is still unresolved (i.e. it is itself defined in terms of C2 : S : C
, which is where you are going with U : P
). Removing : P
in U : P
removes the error, though this may not be what you want. Then again, depending on what you want, there may be any number of solutions :)
编辑
以下是对@ igul222简化的代码示例的响应.但是,我仍然认为,编译器仅返回的是一条不太有用的错误消息,这实际上是由递归类型定义引起的.考虑一下,例如,您是否定义了enum
本身:
The following is in response to @igul222's much simplified code example. I still, think, however, that the compiler is simply returning a less then helpful error message, which is really caused by the recursive type definition. Consider, for example, if you define an enum
in terms of itself:
enum E {
case C(E) // error: recursive value type 'E' is not allowed
}
现在,这可能也是以下问题:
Now, this is probably also the problem with the following:
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'
...也不起作用(您的要旨的版本):
... neither does this work (a version of your gist):
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`'
编译器似乎在说的是C<Self>
中的Self
尚未A
,即A
尚未Self
,因为要成为A
,它必须符合C<Self>
检出...但是以下方法可行,因为A
不再就其本身定义关联的类型:
What the compiler seems to be saying is that Self
in C<Self>
is not yet A
, i.e. that A
is not yet itSelf
since to be A
it must conform to P
which is in turn pending C<Self>
checking out... But the following works because A
no longer defines an associated type in terms of itself:
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中使用它.但是,目前,即使编译器允许定义它,我不确定一个人是否可以有效地遵循一种相关类型为T<Self>
的协议...否则,这一切都应该在运行时起作用.
Some patterns of functional programming require recursively defined types, so it might be nice to have that in Swift. At present, however, I am not sure one can usefully conform to a protocol with an associated type of the form T<Self>
, even though the compiler allows its definition... otherwise, this should all just work at runtime.
我刚升级到 Xcode 6.1 GM种子,事情发生了变化!以下以前没有编译过的代码段现在可以编译并且运行正常!
I have just upgraded to Xcode 6.1 GM Seed and things have changed! The following snippet, that would not have compiled before, now compiles and appears to run fine!
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 // --> {{{...}}}
但是,此改进并未扩展到递归定义的关联类型.
This improvement, however, does not extend to recursively defined associated types.
这篇关于类型X不继承自Y的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!