我正在尝试做一些类似的事情:
protocol Protocol {
associatedtype T
associatedtype ArrayT = Array<T>
}
struct Struct<ProtocolType: Protocol> {
func doSomething(with: ProtocolType.ArrayT) {
let _ = with.map { $0 }
// ^ compiler complains on this line
// "value of type ProtocolType.ArrayT has no member map"
}
}
其中我定义了一个使用 linkedtype
T
的便利类型别名 ArrayT
。似乎当我尝试像 doSomething(_:)
中那样使用 ArrayT
时,我丢失了 ArrayT< 的
。 Array
类型信息
ArrayT
不应该绝对是一个 Array
并因此成为 Sequence
协议(protocol)的成员,从而公开 map
功能? 🤔
我现在采用的工作解决方案是在协议(protocol)之外定义一个通用类型别名:
typealias ProtocolArray<ProtocolType: Protocol> = Array<ProtocolType.T>
struct Struct<ProtocolType: Protocol> {
func doSomething(with: ProtocolArray<ProtocolType>) {
let _ = with.map { $0 } // no complaints
}
}
我在这里缺少什么?
最佳答案
线路associatedtype ArrayT = Array<T>
仅告诉编译器 ArrayT
的默认值是 Array<T>
。协议(protocol)的改编仍然可以改变 ArrayT
像:
struct U: Protocol {
typealias T = UInt32
typealias ArrayT = UInt64 // <-- valid!
}
如果您想要固定类型,则应该使用类型别名...
// does not work yet.
protocol Protocol {
associatedtype T
typealias ArrayT = Array<T>
}
但是编译器提示类型太复杂🤷。因此,您能做的最好的事情就是限制 ArrayT
成为序列/集合/等,并希望适配器不会自行更改类型。
// still somewhat off
protocol Protocol {
associatedtype T
associatedtype ArrayT: Sequence = [T]
}
但是请注意,序列可以有任何元素类型,但我们希望 ArrayT 的元素必须是 T。我们不能附加 where
关联类型的子句:
// fail to compile: 'where' clause cannot be attached to an associated type declaration
associatedtype ArrayT: Sequence where Iterator.Element == T = [T]
相反,您需要在每次使用协议(protocol)时设置此约束:
struct Struct<ProtocolType: Protocol>
where ProtocolType.ArrayT.Iterator.Element == ProtocolType.T {
完整的工作代码:
protocol Protocol {
associatedtype T
associatedtype ArrayT: Sequence = [T]
// ^~~~~~~~~~
}
struct Struct<ProtocolType: Protocol>
where ProtocolType.ArrayT.Iterator.Element == ProtocolType.T
// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
{
func doSomething(w: ProtocolType.ArrayT) {
let _: [ProtocolType.T] = w.map { $0 }
}
}
关于swift - 为什么这会造成这么多麻烦? (相关类型的协议(protocol)和类型别名),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39629358/