【发布时间】:2020-11-15 21:37:43
【问题描述】:
这是我的问题:
假设我有一个协议,其中associatedtype 指代它的元类型:
protocol TestMeta {
associatedtype T
var x : T.Type { get }
var y : T { get }
}
如果我创建一个具体类型的结构,没问题:
struct AMeta : TestMeta {
var x : Int.Type
var y : Int
}
但是如果associatedtype 指的是协议,我得到了 “Type 'BMeta' does not conform to protocol 'TestMeta'” 错误:
protocol P { }
struct BMeta : TestMeta {
var x : P.Type
var y : P
}
(即使我添加了typealias 定义来帮助推理引擎)
当然,如果我不引用元类型,一切都适用于具体的类型和协议,即使我有其他未在协议中定义的元类型变量:
protocol TestNoMeta {
associatedtype T
var z : T { get }
}
struct ANoMeta : TestNoMeta {
var z : Int
var t : Int.Type
}
struct BNoMeta : TestNoMeta {
var z : P
var t : P.Type
}
如果有人能解释我做错了什么?我怎样才能实现我的目标?提前致谢。
编辑:但正如@New Dev 指出的那样,我没有解释我在寻找什么。我希望能够做这样的事情:
struct S : P { }
let b = BMeta(x: S.self, y: S())
知道它仍在使用 NoMeta 协议进行编译:
let bb = BNoMeta(z: S(), t: S.Type)
EDIT 2:最后我希望做这样的事情:
protocol P {
init()
}
extension TestMeta {
func build() -> P {
return x.init()
}
}
struct BMeta : TestMeta {
var x : P.Type
var y : P
}
struct S : P { }
let b = BMeta(x: S.self, y: S())
let c = b.build()
编辑 3:好的,好的,这是我的真实用例,我认为简化事情会更好,但似乎不是......
protocol Initializable {
init()
}
protocol OptionListFactory {
associatedtype Option : Initializable
static var availableOptions: [Option.Type] { get }
}
extension OptionListFactory {
static func build(code: Int) -> Option? {
if code >= 0 && code < availableOptions.count {
return availableOptions[code].init()
}
else {
return nil
}
}
}
protocol Contract : Initializable {
...
}
struct Contract01 : Contract { ... }
struct Contract02 : Contract { ... }
...
struct Contract40 : Contract { ... }
struct ContractFactory : OptionListFactory {
static let availableOptions: [Contract.Type] = [
Contract01.self,
Contract02.self,
...
Contract40.self,
]
}
protocol Element : Initializable {
...
}
struct Element01 : Element { ... }
struct Element02 : Element { ... }
...
struct Element20 : Element { ... }
struct ElementFactory : OptionListFactory {
static let availableOptions: [Element.Type] = [
Element01.self,
Element02.self,
...
Element20.self,
]
}
希望你能更好地理解我的目的......
【问题讨论】:
-
不确定您要实际实现的目标,但要将其编译为
var x : P.Protocol -
不幸的是,这并不意味着相同。例如,如果我使用您的解决方案创建一个符合
P:struct S : P { }的结构,我不能这样做:let b = BMeta(x: S.self, y: S())因为编译器无法将S.Type转换为P.Protocol -
将协议称为类型的元是很奇怪的,元应该是具体的,而不是抽象的。为什么你需要这个设计,你的最终目标是什么?
-
@Cristik IRL,
P将包含init()用于构建实例的扩展。 -
为什么不在这里使用泛型?
标签: swift generics protocols associated-types