使用Swift在子协议中指定父协议的关联类型

时间:2023-01-23 22:47:57

In Swift 2, I have a protocol:

在Swift 2中,我有一个协议:

protocol Protocol {
    typealias Type
}

When I want to use Protocol without defining what type to use for Type:

当我想使用协议而不定义类型时:

var protocol1: Protocol

Then I'm getting the following error:

然后我得到了以下错误:

Protocol 'Protocol' can only be used as a generic constraint because it has Self or associated type requirements

协议“Protocol”只能用作通用约束,因为它具有自类型或关联类型需求

It is clear why this is not going to work.

很明显,这是行不通的。


I have another protocol, which inherits from the first protocol and specifies that the associated type Type should be a String.

我有另一个协议,它继承自第一个协议,并指定关联类型应该是字符串。

protocol AnotherProtocol: Protocol {
    typealias Type = String
}

The same error occurs, when I try to use this protocol:

当我尝试使用这个协议时,同样的错误发生了:

var protocol2: AnotherProtocol

Protocol 'AnotherProtocol' can only be used as a generic constraint because it has Self or associated type requirements

协议“AnotherProtocol”只能用作通用约束,因为它具有自类型或关联类型需求

Why am I getting an error for this, although I have specified the associated type?

为什么会出现错误,尽管我已经指定了关联类型?

Is there another way for the second protocol to specify the associated type of the parent protocol, without having to specify it again in every class that implements the second protocol?

第二个协议是否有另一种方法来指定父协议的关联类型,而不必在实现第二个协议的每个类中再次指定它?

1 个解决方案

#1


2  

Your error isn't coming from the declaration or definition of your protocols, it comes from how you're trying to use them. There are two basic ways you can use a protocol: as a pseudo-type, or as a constraint. When you declare a variable like this:

您的错误不是来自协议的声明或定义,而是来自您如何使用它们。使用协议有两种基本方式:伪类型或约束。当你像这样声明一个变量时:

var protocol1: Protocol

You're using the protocol like it's a type: the type of protocol1 is Protocol. This is different from using it as a constraint. Other types conform to the protocol if it's used as a constraint:

您使用协议就像它是一种类型:协议1的类型是协议。这与使用它作为约束是不同的。其他类型符合协议,如果它被用作约束:

struct SomeStruct: Protocol {...

Now, you can use your protocols in either way, but there are some disadvantages to both ways. Firstly, you can't store a heterogenous collection of "protocols as a constraint", whereas you can when you use protocols as a type.

现在,您可以以任何一种方式使用您的协议,但是两种方式都有一些缺点。首先,不能将“协议作为约束”的异构集合存储,而可以将协议作为类型使用。

Secondly, if there are requirements on self or associated types, you can no longer use that protocol as a type.

其次,如果对自类型或关联类型有需求,则不能再将该协议用作类型。

So, here's what I think you're looking for. Your first protocol:

所以,这就是我认为你在寻找的东西。你的第一个协议:

protocol Protocol {
  typealias Type
}

And then the second:

第二个:

protocol InheritingProtocol {
  typealias Type = String
}

Now, if you want something to conform to the second protocol, it must be used as a constraint. That means that some type conforms to the protocol, and then you can have some instance of that type.

现在,如果您希望某些东西符合第二个协议,那么必须将它用作约束。这意味着某些类型符合协议,然后您可以拥有该类型的一些实例。

struct SomeType : InheritingProtocol {}

let someInstance = SomeType()

#1


2  

Your error isn't coming from the declaration or definition of your protocols, it comes from how you're trying to use them. There are two basic ways you can use a protocol: as a pseudo-type, or as a constraint. When you declare a variable like this:

您的错误不是来自协议的声明或定义,而是来自您如何使用它们。使用协议有两种基本方式:伪类型或约束。当你像这样声明一个变量时:

var protocol1: Protocol

You're using the protocol like it's a type: the type of protocol1 is Protocol. This is different from using it as a constraint. Other types conform to the protocol if it's used as a constraint:

您使用协议就像它是一种类型:协议1的类型是协议。这与使用它作为约束是不同的。其他类型符合协议,如果它被用作约束:

struct SomeStruct: Protocol {...

Now, you can use your protocols in either way, but there are some disadvantages to both ways. Firstly, you can't store a heterogenous collection of "protocols as a constraint", whereas you can when you use protocols as a type.

现在,您可以以任何一种方式使用您的协议,但是两种方式都有一些缺点。首先,不能将“协议作为约束”的异构集合存储,而可以将协议作为类型使用。

Secondly, if there are requirements on self or associated types, you can no longer use that protocol as a type.

其次,如果对自类型或关联类型有需求,则不能再将该协议用作类型。

So, here's what I think you're looking for. Your first protocol:

所以,这就是我认为你在寻找的东西。你的第一个协议:

protocol Protocol {
  typealias Type
}

And then the second:

第二个:

protocol InheritingProtocol {
  typealias Type = String
}

Now, if you want something to conform to the second protocol, it must be used as a constraint. That means that some type conforms to the protocol, and then you can have some instance of that type.

现在,如果您希望某些东西符合第二个协议,那么必须将它用作约束。这意味着某些类型符合协议,然后您可以拥有该类型的一些实例。

struct SomeType : InheritingProtocol {}

let someInstance = SomeType()