类型X不继承自Y [英] Type X does not inherit from Y

查看:101
本文介绍了类型X不继承自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作为要检查的具体类型.不幸的是,此时BP的一致性仍未解决(即,它本身是根据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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆