Достаточно ли автосоответствия?

Видеоверсия этой статьи доступна по адресу https://youtu.be/h-xlW1pEBGI.

Элементы в наборе или словаре должны соответствовать Hashable

Обычно это означает, что нам нужно убедиться, что наш тип соответствует Hashable. В этом примере мы собираемся поместить в набор простое животное struct. Если мы не заявляем о соответствии Hashable Swift, мы получаем довольно обнадеживающую ошибку:

однако компилятор может дать нам автоматическое Hashaable соответствие, мы говорим компилятору, что нам требуется Hashable соответствие (как и мы, чтобы поместить экземпляры struct в набор). Это похоже на следующий фрагмент кода:

struct Animal: Hashable {
    let animalName: String
}
let dog = Animal(animalName: "dog")
let cat = Animal(animalName: "cat")
let animalSet: Set<Animal> = [dog, cat]

Поскольку свойство String по умолчанию соответствует Hashable, больше работать не нужно (ознакомьтесь с этой статьей, чтобы узнать о работе, которая может потребоваться для более сложных типов, чтобы соответствовать протоколу Hashable).

Это абсолютно нормально. Но как насчет использования enum? Мы могли бы сделать это, чтобы добавить типы в set, что, конечно, немного иная ситуация. Однако для целей этой статьи это покажет суть:

enum Animal {
    case dog
    case cat
}
let animalSet: Set<Animal> = [.cat, .dog]

Разница здесь в том, что перечисление (enum) получает Hashable соответствие автоматически - вам даже не нужно объявлять, что enum соответствует Hashable! Потрясающий!

А как насчет связанных типов?

Мы могли бы добавить это в наш enum, но мы не получаем автоматического соответствия:

enum Animal {
    case dog(breed: String)
    case cat(breed: String)
}
let animalSet: Set<Animal> = [.cat(breed: “moggy”), .dog(breed: “lab”)]

К счастью, поскольку связанное значение (в данном случае) Hashable, поскольку они просто String, мы можем (в этом случае) объявить соответствие Hashable с той же легкостью, что и в struct выше:

enum Animal: Hashable {
     case dog(breed: String)
     case cat(breed: String)
}
let animalSet: Set<Animal> = [.cat(breed: "moggy"), .dog(breed: "lab")]

Вывод

Очень заманчиво использовать компилятор для устранения ошибок в коде, и это избавляет вас от необходимости думать, чтобы быстро решать проблемы кода. Однако знание того, что происходит, когда мы получаем эти Hashable ошибок, и то, как мы можем их решить, является ключом к быстрому созданию отличного кода.

Конечно, мы не должны перестать думать о нашем коде, и в случае enum получить что-то «бесплатно» не означает, что мы не должны думать о том, что происходит под капотом.

Надеюсь, эта статья была вам полезна.

Если у вас есть вопросы, комментарии или предложения, пишите мне в Twitter.