2015-06-17 5 views
3

короткий вопрос здесь:Swift словарь с протоколом типа как ключевой

я получил протокол protocol SCResourceModel {..} и словарь, который будет использовать этот тип протокола, как ключ: [SCResourceModel : String]. Это явно не работает, так как ключ в словаре должен соответствовать протоколу Hashable. Делать мой SCResourceModel наследовать от Hashable или пробовать что-то вроде этого [protocol<SCResourceModel, Hashable> : String] явно не работает, так как Hashable или Equatable могут использоваться только как общие ограничения, а не как сами типы.

Я смотрел WWDC 2015 и в Swift 2.0 можно добавить ограничения на такой протокол, как: protocol SCResourceModel where Self: Hashable {..}, который непосредственно решает эту проблему (очень приятно).

В любом случае, мой вопрос: могу ли я сделать что-то подобное с текущей версией Swift 1.2 и каким-то образом использовать этот протокол в качестве ключа словаря? Или может кто-нибудь предложить хорошее обходное решение или что-то еще, что я мог упустить?

Единственное решение, которое я вижу на данный момент для Swift 1.2, заключается в преобразовании протокола в класс, который наследуется, например, NSObject и должен быть подклассифицирован для дальнейшего использования в моем API.

Благодарим за помощь!

+0

Вы, наверное, имели в виду Swift 1.2, нет 1,3. Он должен работать как 'protocol SCResourceModel: Hashable {}' Или есть ли ошибка для вас? Если да, покажите свой (минимальный) код – Kametrixom

+0

Я исправил версию :) Ваше предложение не работает, так как это делает 'SCResourceModel'' Hashable' Type. Нельзя использовать это как Тип только как общее ограничение (оно не компилируется). Код уже в этом вопросе. Протокол и словарь, две строки. Дайте мне знать, если у вас есть другие вопросы. – croX

ответ

2

Хорошо, насколько я могу судить, нет действительно хорошего способа иметь сам протокол в качестве ключа. Но я уверен, что строковая версия имени протокола будет работать хорошо для вашей цели. В качестве бонуса вы также можете иметь объекты протокола в качестве значения в словаре (если это полезно в ваших обстоятельствах)

Дело в том, что я не могу найти хороший способ сделать это в Swift, но здесь что я придумал в Objective-C, может быть, вы бы лучше меня найти способ сделать это в Swift:

// With a protocol declared... 
@protocol TestProtocol <NSObject> 
@end 

@implementation 

// Inside the implementation you can use NSStringFromProtocol() 
Protocol *proto = @protocol(TestProtocol); 
NSLog(@"Protocol: %@", NSStringFromProtocol(proto)); 

@end 

выходы:

Protocol: TestProtocol 

@protocol часть этого код - это часть, в которой я не уверен, что делать в Swift, и если хуже, ys в файл Objective-C. Надеюсь, это даст вам некоторые идеи!

+0

Спасибо за ваши идеи – croX

5

я бы, вероятно, думать в направлении:

protocol SCResourceModel { 
    var hashValue: Int { get } 
    func isEqualTo(another: SCResourceModel) -> Bool 

    // ... 
} 

struct SCResourceModelWrapper: Equatable, Hashable { 
    let model: SCResourceModel 

    var hashValue: Int { 
     return model.hashValue^"\(model.dynamicType)".hashValue 
    } 
} 

func == (lhs: SCResourceModelWrapper, rhs: SCResourceModelWrapper) -> Bool { 
    return lhs.model.isEqualTo(rhs.model) 
} 

struct SCResourceModelDictionary<T> { 
    private var storage = [SCResourceModelWrapper: T]() 

    subscript(key: SCResourceModel) -> T? { 
     get { 
      return storage[SCResourceModelWrapper(model: key)] 
     } 
     set { 
      storage[SCResourceModelWrapper(model: key)] = newValue 
     } 
    } 
} 
+0

Хорошее обходное решение для создания пользовательского словаря. Мне это нравится! – croX

Смежные вопросы