Не в состоянии использовать протокол в качестве ключа в словаре в Swift

Я разрабатываю функциональность для двух подмножеств одного типа. например. фрукты. У меня есть два перечисления для фруктов, как показано ниже:

enum SourFruits: String {
    case Grape, Orange, Lemon
}

enum SweetFruits: String {
    case Watermelon, Banana, Apple
}

Чтобы использовать эти два как один тип в моей реализации, я использую протокол:

protocol Fruits {
}
extension SweetFruits: Fruits {
}
extension SourFruits: Fruits {
}

Теперь вот моя реализация выглядит так:

func doCommonOnFruit(fruit: Fruits) {
    //Do common
}
func doSomeThingWithSourFruit(fruit: SourFruits) {
    doCommonOnFruit(fruit)
    // Do specific
}
func doSomeThingWithSweetFruit(fruit: SweetFruits) {
    doCommonOnFruit(fruit)
    // Do specific
}

Это работает нормально, но когда я пытаюсь добавить его на карту в качестве ключа:

let map: [Fruit : String] = [:]

Это подскажет мне ошибку говорит: Type 'Fruit' does not confirm to protocol 'Hashable', Моя карта должна содержать любые (сладкие или кислые фрукты в качестве ключа). Как этого добиться.

Я пытался реализовать Hashable во фруктах, но это не сработало. Пожалуйста, помогите мне в этом.

2 ответа

Вы не можете использовать протокол здесь - протоколы на самом деле не какого-либо типа... это просто определение. то же самое может быть достигнуто через класс.

 class Fruits : NSObject {
    }

Теперь определите, подкласс фруктов. Вы можете перечислить как часть подкласса.

class SweetFruits: Fruits  {
    enum SweetFruits: String {
        case Watermelon, Banana, Apple
    }


}
class SourFruits: Fruits {
    enum SourFruits: String {
        case Grape, Orange, Lemon
    }

}

в общем методе вы можете получить к нему доступ следующим образом...

func doCommonOnFruit(fruit: Fruits) {

    if(fruit.isKind(of: SourFruits.classForCoder()))
    {

    }
    if(fruit.isKind(of: SweetFruits.classForCoder()))
    {

    }
    //Do common
}
func doSomeThingWithSourFruit(fruit: SourFruits) {
    doCommonOnFruit(fruit: fruit)
    // Do specific
}
func doSomeThingWithSweetFruit(fruit: SweetFruits) {
    doCommonOnFruit(fruit: fruit)
    // Do specific
}

// Вы можете напрямую использовать Enum с именем класса, как показано ниже.

func test()
{
    let map: [Fruits : String] = [:]
    let  test  = SourFruits.SourFruits.Grape
}

Если протокол 'Fruits' соответствует протоколу 'Hashable', его можно использовать только как общее ограничение, поскольку он имеет Self или требования к связанному типу.

Другие вопросы по тегам