Swift 使用关联类型和泛型时出错

Swift 使用关联类型和泛型时出错,swift,Swift,下面的代码在第行返回p.foo(self)时给出了一个错误。错误显示:'P'没有名为'foo'的成员。 protocol P { typealias T func foo(c: C<T>) -> T func foo2() -> T } class C<T> { var p: P init (p: P) { self.p = p } func bar() -> T { return p.foo(self);

下面的代码在第
行返回p.foo(self)
时给出了一个错误。错误显示:
'P'没有名为'foo'的成员。

protocol P {
  typealias T
  func foo(c: C<T>) -> T
  func foo2() -> T
}

class C<T> {
  var p: P
  init (p: P) {
    self.p = p
  }
  func bar() -> T {
    return p.foo(self);
  }
}
协议P{
别名T
func-foo(c:c)->T
func foo2()->T
}
C类{
var p:p
初始(p:p){
self.p=p
}
func bar()->T{
返回p.foo(self);
}
}
协议
p
定义了一个关联类型,该类型应与任何专门的C类型正确匹配。我错过什么了吗?是否?

来自:

协议本身并没有实现任何功能。尽管如此,您创建的任何协议都将成为在代码中使用的成熟类型


为了使用
.foo
方法,您需要一个
结构
来实现您的
协议

您从未要求两个
T
匹配。它们都在各自的范围内。因此,编译器会查找参数类型错误的
foo
函数

我相信这样做是正确的:

protocol P {
    typealias T
    func foo<ConcreteP>(c: C<T, ConcreteP>) -> T
    func foo2() -> T
}

class C<T, ConcreteP: P where T == ConcreteP.T> {
    var p: ConcreteP
    init (p: ConcreteP) {
        self.p = p
    }
    func bar() -> T {
        return p.foo(self);
    }
}

这听起来像是一个编译器错误。

在回答问题之前,我将对类型重命名一点,以使问题更清楚:

protocol P {
  typealias ElementType
  func foo(c: C<ElementType>) -> ElementType
  func foo2() -> ElementType
}

class C<T> {
  var p: P
  init (p: P) {
    self.p = p
  }
  func bar() -> T {
    return p.foo(self)
  }
}
这将消除初始值设定项的编译器错误。现在编译器知道参数必须是P的子类型,并且有效的子类型总是指定ElementType是什么,所以它很高兴

但这并不能帮你做到这一点:

var p: P
您仍然不能在此处使用不完整类型
p
。您可能希望使用
S
,但目前初始化器中的
S
与您将用作变量类型的S之间没有联系,但它们显然需要相同。 是时候向类中引入第二个泛型参数了:

class C<T, S:P> {
    var p: S
    init (p: S) {
        self.p = p
    }
    func bar() -> T {
        return p.foo(self)
    }
}
现在,我们指定由任何确认类型实现的foo函数实际上使用具有指定ElementType和实现类型本身的C。真想不到,不是吗

但我们还没有完全完成,最后一个错误仍然存在:

error: <EXPR>:13:18: error: cannot convert the expression's type 'T' to type 'S.ElementType'
        return p.foo(self)
完整代码:

protocol P {
    typealias ElementType
    func foo(c: C<ElementType, Self>) -> ElementType
    func foo2() -> ElementType
}

class C<T, S:P where S.ElementType == T> {
    var p: S
    init (p: S) {
        self.p = p
    }
    func bar() -> T {
        return p.foo(self);
    }
}
协议P{
类型别名元素类型
func-foo(c:c)->ElementType
func foo2()->ElementType
}
C类{
var p:S
初始(p:S){
self.p=p
}
func bar()->T{
返回p.foo(self);
}
}

您是否尝试过使用mutating func而不仅仅是func?不太正确。您不必首先定义实现该协议的类或结构。在这种情况下,这甚至不能解决问题。根本问题是,P不能用作变量/参数的类型,因为它没有完全指定,因为缺少关联的类型。没有关联类型的协议应该可以工作。或者,指定变量必须是P的子类型也可以,正如我在回答中所做的那样。
class C<T, S:P> {
    var p: S
    init (p: S) {
        self.p = p
    }
    func bar() -> T {
        return p.foo(self)
    }
}
func foo(c: C<ElementType>) -> ElementType
: type 'P' does not conform to protocol 'P'
    func foo(c: C<ElementType, P>) -> ElementType
                ^
<EXPR>:2:15: note: associated type 'ElementType' prevents protocol from conforming to itself
    typealias ElementType
protocol P {
    typealias ElementType
    func foo(c: C<ElementType, Self>) -> ElementType
    func foo2() -> ElementType
}
error: <EXPR>:13:18: error: cannot convert the expression's type 'T' to type 'S.ElementType'
        return p.foo(self)
class C<T, S:P where S.ElementType == T> {
protocol P {
    typealias ElementType
    func foo(c: C<ElementType, Self>) -> ElementType
    func foo2() -> ElementType
}

class C<T, S:P where S.ElementType == T> {
    var p: S
    init (p: S) {
        self.p = p
    }
    func bar() -> T {
        return p.foo(self);
    }
}