Ответ 1
Возможно, есть лучшее решение, но вы можете сделать свой класс общим:
protocol testProtocol : Hashable {
//
}
class test<P: testProtocol> {
var s : Set<P>?
init() { }
}
Есть ли способ сделать следующее на самом деле работать?
protocol testProtocol {
//
}
class test {
var s : Set<testProtocol>?
init(){
}
}
protocol testProtocol : Hashable {
//
}
class test {
var s : Set<testProtocol>?
init(){
}
}
Я предполагаю, что ответа нет, потому что протоколы (даже с тегом @objc) не имеют достаточной информации? но, может быть, есть какая-то строка или вещь, которую я здесь отсутствует.
Возможно, есть лучшее решение, но вы можете сделать свой класс общим:
protocol testProtocol : Hashable {
//
}
class test<P: testProtocol> {
var s : Set<P>?
init() { }
}
Одно из решений состоит в том, чтобы обернуть набор в класс или структуру и ограничить функцию вставки так, чтобы она принимала только те элементы, которые соответствуют вашему протоколу и допускают хэширование. Затем вы можете использовать Set
AnyHashable
в реализации.
Например:
protocol MyProtocol {
func doStuff()
}
class MyProtocolSet {
var set = Set<AnyHashable>()
func insert<T>(_ item: T) where T: MyProtocol, T: Hashable {
set.insert(AnyHashable(item))
}
func iterate( doing: (MyProtocol) -> Void ) {
for item in set {
doing(item as! MyProtocol)
}
}
}
struct Foo: MyProtocol, Hashable {
func doStuff() { print("foo") }
}
struct Bar: MyProtocol, Hashable {
func doStuff() { print("bar") }
}
func test() {
let set = MyProtocolSet()
set.insert(Foo())
set.insert(Bar())
set.iterate { (item: MyProtocol) in
item.doStuff()
}
}
Налагая ограничения на функцию вставки, вы говорите, что "этот набор должен содержать вещи, которые соответствуют протоколу и являются хэшируемыми", фактически не ограничивая протокол хэшируемостью.
Было бы еще лучше, если бы класс оберточного набора сам по себе был бы универсальным и принимал протокол для соответствия, но я пока не выяснил, возможно ли это!
Я знаю, что это не Set
(как и заданный вопрос), но вы можете использовать NSHashTable
вместо Set
. Вы должны будете выставить свой протокол на objc. Хотя это и не Set
, если вы просто хотите сохранить коллекцию объектов протокола без необходимости соответствовать Hashable
, это будет работать:
@objc protocol testProtocol { }
class Object {
var s: NSHashTable<testProtocol>!
}
Таким образом, вы можете использовать предоставляемые функции add
и remove
.
Кроме того, если вы храните наблюдатели или что-то подобное, вы можете инициализировать хеш-таблицу с помощью NSHashTable.weakObjects()
, которая обеспечит сохранение объектов.
Вот больше о NSHashTable
: https://developer.apple.com/documentation/foundation/nshashtable