Полиморфизм
Часть раздела Объектно-ориентированное программирование путешествия по Swift на Coddy. Урок 32 из 57.
Полиморфизм означает, что один фрагмент кода работает со значениями разных типов, и каждое значение отвечает по-своему. Цикл ниже вызывает sound(), не зная, какое животное в нём хранится:
class Animal {
func sound() -> String { "..." }
}
class Dog: Animal {
override func sound() -> String { "Woof" }
}
class Cow: Animal {
override func sound() -> String { "Moo" }
}
let farm: [Animal] = [Dog(), Cow(), Dog()]
for a in farm { print(a.sound()) }Вывод:
Woof
Moo
WoofSwift решает, какую реализацию запустить во время выполнения, исходя из фактического объекта. Объявленный тип переменной не имеет значения; важен тип объекта:
class Animal {
func sound() -> String { "..." }
}
class Cat: Animal {
override func sound() -> String { "Meow" }
}
let pet: Animal = Cat()
print(pet.sound())Вывод:
MeowПротоколы предоставляют такую же гибкость структурам и перечислениям. Здесь одна функция выводит любой список значений Drawable:
protocol Drawable {
func draw() -> String
}
struct Line: Drawable {
let length: Int
func draw() -> String { String(repeating: "-", count: length) }
}
struct Box: Drawable {
func draw() -> String { "[ ]" }
}
func render(_ items: [any Drawable]) -> String {
items.map { $0.draw() }.joined(separator: " ")
}
print(render([Line(length: 3), Box(), Line(length: 1)]))Вывод:
--- [ ] -Полиморфизм заменяет длинные цепочки if/switch для разных видов объектов. Вместо того чтобы выяснять, чем является значение, а затем решать, что с ним делать, вы просите значение выполнить это действие. Добавление нового вида означает добавление нового типа, а не редактирование каждого switch:
// без полиморфизма
if kind == "dog" { print("Woof") } else if kind == "cow" { print("Moo") }
// с полиморфизмом
for animal in farm { print(animal.sound()) }Задание
ЛегкоAnimal содержит name, legs() (4) и describe(), который возвращает Rex has 4 legs and says Woof, сформированный на основе legs() и sound(). Объявите Dog (звук Woof), Bird (2 ноги, звук Tweet) и Snake (0 ног, звук Hiss), переопределяя только legs() и sound().
Предоставленный код считывает строки dog,Rex, bird,Pip или snake,Kaa, сохраняет животных в одном массиве [Animal] и выводит describe() для каждого.
Ваш код должен находиться в файлах Animal.swift, Dog.swift, Bird.swift и Snake.swift. В main.swift находится предоставленный код ввода/вывода, и его нельзя редактировать.
Попробуйте сами
// Предоставленный код ввода/вывода: оставьте его как есть
var input: [String] = []
while let line = readLine() { input.append(line) }
var zoo: [Animal] = []
for line in input {
let p = line.split(separator: ",").map(String.init)
switch p[0] {
case "dog": zoo.append(Dog(name: p[1]))
case "bird": zoo.append(Bird(name: p[1]))
default: zoo.append(Snake(name: p[1]))
}
}
for a in zoo { print(a.describe()) }
В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.
Все уроки раздела Объектно-ориентированное программирование
1Классы и объекты
Работа с файламиОпределение классовМетоды и selfИнициализаторыКлассы — это ссылкиПовторение — читательский билет4Инкапсуляция
Контроль доступаТолько чтение извнеЗащита состоянияИнициализаторы с возможностью сбояПовторение — банковский счёт7Полиморфизм и обобщения
ПолиморфизмПриведение типовОбобщённые функцииОбобщённые типыПовторение — калькулятор фигур10Паттерны проектирования. Часть 2
Паттерн делегированияПаттерн декораторПаттерн строительПаттерн состояния2Структуры и типы-значения
СтруктурыСемантика значенийИзменяющие методыСтруктура или классПовторение — элемент инвентаря5Наследование
ПодклассыПереопределение методовИнициализаторы и superfinal и иерархииПовторение — иерархия сотрудников8Стандартные протоколы
CustomStringConvertibleEquatableComparableHashableПовторение — пользовательская сортировка11Проект: Управление библиотекой
Книги и читателиВыдача книгПотренируйтесь самостоятельно: Песочница Swift