Требовать тип и протокол для параметра метода
Я играю с Swift и спотыкаюсь о следующей проблеме: учитывая, что у меня есть предопределенный класс Animal
:
//Predefined classes
class Animal {
var height: Float = 0.0
}
Теперь я напишу класс Zoo
с конструктором, принимающим животных. Но Zoo
хочет, чтобы каждое животное имело имя и, следовательно, определяло протокол Namable
.
protocol Namable {
var name: String {get}
}
class Zoo {
var animals: Animal[] = [];
}
Как вы напишете метод addAnimal
, который требует, чтобы объект, передаваемый как параметр, был как Animal
, так и соответствовать протоколу Namable
? И как вы объявляете это для массива animals
?
func addAnimal:(animal: ????) { ... }
В Objective-C я бы написал что-то вроде этого
- (void)addAnimal:(Animal<Namable>*)animal {...}
Ответы
Ответ 1
Вы можете использовать общий код с предложением where
с несколькими условиями.
func addAnimal<T: Animal where T: Nameable>(animal: T) { ... }
Поправка. Вероятно, вы должны сделать весь класс таким общим, чтобы правильно ввести массив
class Zoo<T: Animal where T: Nameable> {
var animals : T[] = []
func addAnimal(a: T) {
...
}
}
Ответ 2
Для меня это выглядит скорее проблемой архитектуры:
Nameable
является странным как протокол. Логически каждое животное имеет возможность быть названным так Animal
должно всегда соответствовать Nameable
Было бы гораздо проще разрешить имена nil
, когда животное не будет названо, вместо того, чтобы иметь животных, которые могут иметь имя и животных, которые не могут.
Затем вы можете назначать имена в Zoo
просто assert
.
Ответ 3
<>
находится в Objective-C: соответствует протоколу
<>
находится в Swift для дженериков
Вы можете сделать больше с ключевым словом where
Используйте , где, после имени типа, чтобы указать список требований, например, чтобы потребовать, чтобы тип выполнял протокол, чтобы требовать, чтобы два типа были одинаковыми или требовали, чтобы класс имеют специальный суперкласс.
Отрывок из: Apple Inc. "Быстрый язык программирования". iBooks.
Ответ 4
версия Swift 3
В Swift 3 структура немного изменилась. Вот почему вы получите предупреждение об устаревании старой структуры. Вот новый:
Для функций ожидаемые протоколы расположены после определения параметров функции. Пример:
func addAnimal<T: Animal>(animal: T) where T: Nameable
Для перечислений или классов структура также изменилась
enum ZooEnum<T: Animal> where T: Nameable
class Zoo<T: Animal> where T: Nameable