Вот моя проблема:
Допустим, у меня есть протокол, в котором 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
относится к протоколу, у меня возникает ошибка Тип 'BMeta' не соответствует протоколу '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
}
Итак, если кто-нибудь может объяснить, что я делаю неправильно? И как я могу достичь своей цели? Заранее спасибо.
EDIT: Но, как указал @New Dev, я не объяснил, что искал. Я хочу иметь возможность сделать что-то вроде этого:
struct S : P { }
let b = BMeta(x: S.self, y: S())
Зная, что все еще компилируется с протоколом NoMeta:
let bb = BNoMeta(z: S(), t: S.Type)
РЕДАКТИРОВАТЬ 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
- person New Dev   schedule 16.11.2020P
:struct S : P { }
с вашим решением, я не могу сделать:let b = BMeta(x: S.self, y: S())
, потому что компилятор не может преобразоватьS.Type
вP.Protocol
- person Zaphod   schedule 16.11.2020P
будет содержатьinit()
для расширения для создания экземпляра. - person Zaphod   schedule 16.11.2020y
? Вы, кажется, не используете его вообще. Я предполагаю, чтоP
является более сложным протоколом, который включаетinit
как одно требование из нескольких? В противном случае протоколP
не имеет большого смысла (вы ничего не можете сделать сc
в вашем примере). - person Rob Napier   schedule 16.11.2020