#swift
#swift
Вопрос:
Предположим, у меня есть протокол с соответствующим типом T
protocol Helper{
associatedtype T
func help(_ item: T)
}
в классе я хочу объявить свойство
class Manager<T>{
let item: T?
let helper: Helper<T>
//Error: Cannot specialize non-generic type 'Helper'
let anotherHelper: Helper
//Error: Protocol 'Helper' can only be used as a generic constraint because it has Self or associated type requirements
}
Как мне объявить и использовать вспомогательное свойство таким образом, чтобы оно применяло тип класса, соответствующий вспомогательному протоколу?
Я уверен, что многие люди, имеющие опыт работы с Java / C # или другими подобными языками, застревают при попытке выполнить аналогичные действия
Ответ №1:
В этом конкретном случае вы могли бы сделать T
in Manager<T>
вместо Helper
:
class Manager<T> where T : Helper {
let item: T.T?
let helper: T
init(helper: T) {
self.helper = helper
item = nil
}
}
И если вы хотите Helper<Int>
, вы делаете:
class IntHelper : Helper {
typealias T = Int
// ...
}
А затем используйте Manager<IntHelper>
.
Комментарии:
1. Даже если это, похоже, решает этот конкретный случай, это не отвечает на вопрос. Обычно T будет моделью, а помощники — это потребители, которые выполняют действие над моделью / с ней. Как бы выглядел код, который выполняет именно это?
Ответ №2:
Возможно, вам понадобится средство удаления типов:
struct AnyHelper<T>: Helper {
private let helpFunc: (T) -> Void
init<H>(_ helper: H) where Helper.T == T {
helpFunc = helper.help
}
func help(_ item: T)
helpFunc(item)
}
}
а затем используйте средство удаления типов в вашем классе:
class Manager<T>{
let item: T?
let helper: AnyHelper<T>
init<H>(item: T, helper: H) where H.T == T {
self.item = item
self.helper = AnyHelper(helper)
}
}