不能将泛型类型的值转换为相关联类型的预期参数

时间:2022-01-15 16:10:24

Maybe I am missing something here, but bare with me. Say I have a protocol:

也许我在这里错过了什么,但对我来说是赤裸裸的。假设我有一个协议:

protocol Foo:Hashable, Comparable {}

And a struct that has this guy as a generic:

还有一个结构它有一个通用的

struct UsingFoo<T:Foo> {}

So far so good. Say I want to use Foo on a second protocol:

目前为止一切都很顺利。假设我想在第二个协议上使用Foo:

protocol Bar {
    associatedtype FooType:Foo
    func doSomething(with:UsingFoo<FooType>)
}

And use Bar on a class:

在课堂上使用Bar:

class UsingBar<F:Foo>:Bar {
    typealias FooType = F
    func doSomething(with: UsingFoo<F>) {}
}

Now say I want to bring these guys to a party:

现在假设我要带这些人去参加一个聚会:

class FooBarParty<F:Foo, B:Bar>: NSObject {
    var b:B
    init(b:B) {
        self.b = b
        // interestingly, this line below won't compile
        // self.b = UsingBar<F>.init()
    }

    func thisWillCompile () {
        UsingBar<F>.init().doSomething(with: UsingFoo<F>.init())
    }

    func thisWontCompile() {
        b.doSomething(with: UsingFoo<F>.init())
    }

    func thisAlsoWont (anotherB:B) {
        anotherB.doSomething(with: UsingFoo<F>.init())
    }
}

The compiler says:

编译器说:

Cannot convert value of type 'UsingFoo<F>' to expected argument type 'UsingFoo<_>'

The question is: How can I ever use a property of type Bar? As always, any comment very appreciated

问题是:如何使用Bar类型的属性?一如既往,任何评论都非常感谢

EDIT: Thanks to the accepted answer I figured out I should have specified FooType. It would look like this:

编辑:感谢大家接受的答案,我发现我应该指定FooType。它看起来是这样的:

class FooBarParty<F:Foo, B:Bar> where B.FooType == F { ... }

1 个解决方案

#1


1  

So the question here basically is:

所以这里的问题基本上是:

Why can't I use an instance of B to call doSomething(UsingFoo<F>()), but I can with an instance of UsingBar<F>

为什么我不能使用一个B实例来调用doSomething(使用foo ())),但是我可以使用一个使用bar 的实例

The problem lies in your associated type - FooType.

问题在于您的关联类型-页脚类型。

The doSomething method says that it only accepts arguments of type UsingFoo<FooType>. We know that in UsingBar<F>, FooType is F. So UsingBar<F>().doSomething requires a UsingFoo<F>. And in thisWillCompile, you give it a UsingFoo<F>! It works!

doSomething方法说它只接受类型UsingFoo 的参数。我们知道在UsingBar 中,FooType是F.所以UsingBar ()doSomething需要UsingFoo < F >。在thisWillCompile中,你给它一个UsingFoo !它的工作原理!

Now you get another random instance of B and call doSomething. What argument does it need? UsingFoo<FooType>, you might say. Well, what is FooType here? We don't know! It can be F, or String if we add this extension right here:

现在你得到另一个B的随机实例,然后调用doSomething。它需要什么论据?UsingFoo < FooType >,你可能会说。那么,FooType是什么呢?我们不知道!它可以是F,也可以是字符串如果我们在这里加上这个扩展:

extension String: Foo { }

FooType can be anything that implements Foo. It doesn't need to be F. But you're passing it a UsingFoo<F>. That's why it does not work!

FooType可以是任何实现Foo的东西。它不一定是F,但你传递它为UsingFoo 。这就是它不能工作的原因!

As you said, this line does not work either:

正如你所说的,这条线也不管用:

self.b = UsingBar<F>.init()

You need to be aware that B is not Bar. It can be any type that implements Bar, not necessarily UsingBar<F>. What you're doing is essentially:

你需要知道B不是Bar。它可以是任何实现Bar的类型,不一定使用Bar 。你所做的基本上是:

class A {}
class B: A {}
class C: A {}
let obj: B = C()

That's why that does not compile.

这就是为什么它不编译的原因。

#1


1  

So the question here basically is:

所以这里的问题基本上是:

Why can't I use an instance of B to call doSomething(UsingFoo<F>()), but I can with an instance of UsingBar<F>

为什么我不能使用一个B实例来调用doSomething(使用foo ())),但是我可以使用一个使用bar 的实例

The problem lies in your associated type - FooType.

问题在于您的关联类型-页脚类型。

The doSomething method says that it only accepts arguments of type UsingFoo<FooType>. We know that in UsingBar<F>, FooType is F. So UsingBar<F>().doSomething requires a UsingFoo<F>. And in thisWillCompile, you give it a UsingFoo<F>! It works!

doSomething方法说它只接受类型UsingFoo 的参数。我们知道在UsingBar 中,FooType是F.所以UsingBar ()doSomething需要UsingFoo < F >。在thisWillCompile中,你给它一个UsingFoo !它的工作原理!

Now you get another random instance of B and call doSomething. What argument does it need? UsingFoo<FooType>, you might say. Well, what is FooType here? We don't know! It can be F, or String if we add this extension right here:

现在你得到另一个B的随机实例,然后调用doSomething。它需要什么论据?UsingFoo < FooType >,你可能会说。那么,FooType是什么呢?我们不知道!它可以是F,也可以是字符串如果我们在这里加上这个扩展:

extension String: Foo { }

FooType can be anything that implements Foo. It doesn't need to be F. But you're passing it a UsingFoo<F>. That's why it does not work!

FooType可以是任何实现Foo的东西。它不一定是F,但你传递它为UsingFoo 。这就是它不能工作的原因!

As you said, this line does not work either:

正如你所说的,这条线也不管用:

self.b = UsingBar<F>.init()

You need to be aware that B is not Bar. It can be any type that implements Bar, not necessarily UsingBar<F>. What you're doing is essentially:

你需要知道B不是Bar。它可以是任何实现Bar的类型,不一定使用Bar 。你所做的基本上是:

class A {}
class B: A {}
class C: A {}
let obj: B = C()

That's why that does not compile.

这就是为什么它不编译的原因。