Menu
Coddy logo textTech

Подклассы

Часть раздела Объектно-ориентированное программирование путешествия по Swift на Coddy. Урок 22 из 57.

Наследование позволяет классу строиться на основе другого класса. class Dog: Animal делает Dog подклассом суперкласса Animal: у собаки есть каждое свойство и метод животного, а также всё, что добавляет Dog:

class Animal {
    var name: String
    init(name: String) { self.name = name }
    func describe() -> String { "\(name) is an animal" }
}

class Dog: Animal {
    func fetch() -> String { "\(name) fetches the ball" }
}

let rex = Dog(name: "Rex")
print(rex.describe())
print(rex.fetch())

Вывод:

Rex is an animal
Rex fetches the ball

Подкласс, который не добавляет хранимых свойств, наследует инициализаторы суперкласса, поэтому Dog(name:) работает без init в Dog. Наследование моделирует отношение «является»: каждая собака — это животное, поэтому Dog можно использовать везде, где ожидается Animal:

class Animal {
    var name: String
    init(name: String) { self.name = name }
}

class Cat: Animal {}
class Dog: Animal {}

let pets: [Animal] = [Cat(name: "Tom"), Dog(name: "Rex")]
for pet in pets { print(pet.name) }

Результат:

Tom
Rex

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

class Vehicle { var wheels = 0 }
class Car: Vehicle { }        // Car является Vehicle
class Bike: Vehicle { }       // Bike является Vehicle
// struct Truck: Vehicle { }  // ошибка: структуры не могут наследовать

Поместите всё, что является общим для всех подклассов, в суперкласс, а в каждый подкласс — только различия. Если один тип на самом деле не является разновидностью другого, наследование — неподходящий инструмент; свойство, содержащее другой тип, часто подходит лучше.

class Shape {
    var name: String
    init(name: String) { self.name = name }
    func label() -> String { "a \(name)" }
}

class Square: Shape {
    var side = 1.0
    func area() -> Double { side * side }
}

let s = Square(name: "square")
s.side = 3
print(s.label())
print(s.area())

Вывод:

a square
9.0
challenge icon

Задание

Легко

Employee хранит name и salary и имеет метод raise(by:), который увеличивает зарплату на указанный процент (с округлением вниз). Объявите подкласс Manager, который добавляет хранимое свойство reports (массив имён, изначально пустой), метод addReport(_:) и метод teamSize(), возвращающий количество подчинённых.

Предоставленный код создаёт менеджера из первой строки (name,salary), добавляет каждое последующее имя в качестве подчинённого, повышает зарплату на 10% и выводит Ada earns 5500 and leads 2.

Ваш код должен находиться в Employee.swift и Manager.swift. В main.swift содержится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

// Предоставленный код ввода/вывода: оставьте его как есть
var input: [String] = []
while let line = readLine() { input.append(line) }
let head = input[0].split(separator: ",").map(String.init)
let boss = Manager(name: head[0], salary: Int(head[1])!)
for name in input.dropFirst() { boss.addReport(name) }
boss.raise(by: 10)
print("\(boss.name) earns \(boss.salary) and leads \(boss.teamSize())")
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Swift