--- slideOptions: transition: slide --- # 4.5. Наследование. Переопределение --- # План занятия 1. Вспоминаем прошлое занятие 2. Наследование: вспоминаем определение 3. Что такое базовый класс? 4. Переопределение свойств и методов класса 5. Переопределение инициализатора 6. Модификатор *final* --- # Вспоминаем прошлое занятие 1. Какие бывают свойства? 2. В какой момент вызывается get, а в какой set? 3. Какие бывают наблюдатели? --- # Наследование Наследование — это возможность одного класса принимать свойства, методы и остальные характеристики у другого класса. В рамках наследования «старый» класс называется суперклассом (или базовым классом), а «новый» — подклассом (или субклассом, или производным классом). #### Синтаксис ``` class SomeSubClass: SomeSuperClass { // тело подкласса } ``` Для создания производного класса `SomeSubClass`, для которого базовым является `SomeSuperClass`, необходимо указать имя суперкласса через двоеточие после имени подкласса. --- # Базовый класс Любой класс, который ничего не наследует из другого класса, называется базовым классом. Классы в Swift ничего не наследуют от универсального базового класса. Классы, у которых не указан супер класс (родительский класс), называются базовыми, которые вы можете использовать для строительства других классов. --- # Переопределение наследуемых элементов Довольно часто реализация метода, который «достался в наследство» от суперкласса, не соответствует требованиям разработчика. В таком случае в сабклассе нужно переписать данный метод, обеспечив к нему доступ по прежнему имени. *Сабкласс* может создавать собственные реализации свойств и методов, наследуемых от *суперкласса*. Такие реализации называются **переопределением**. Для переопределения параметров суперкласса в Swift необходимо указать ключевое слово `override` перед определением элемента. Переопределенный метод не знает деталей реализации метода родительского класса. Он знает лишь имя и перечень входных параметров родительского метода. --- # Доступ к переопределенным элементам суперкласса Несмотря на то что переопределение изменяет реализацию свойств и методов, Swift позволяет осуществлять доступ внутри производного класса к переопределенным элементам суперкласса. Для этого в качестве префикса имени элемента используется ключевое слово `super`. Доступ к переопределенным элементам осуществляется по следующим правилам: * Переопределенный метод с именем `someMethod()` может вызвать одноименный метод суперкласса, используя конструкцию `super`. `someMethod()` внутри своей реализации (в коде переопределенного метода). * Переопределенное свойство someProperty может получить доступ к свойству суперкласса с таким же именем, используя конструкцию `super.someProperty` внутри реализации своего геттера или сеттера. --- # Переопределение инициализаторов Инициализаторы являются такими же наследуемыми элементами, как и методы. Если в подклассе набор свойств, требующих установки значений, не отличается, то наследуемый инициализатор может быть использован для создания экземпляра подкласса. Вы можете создать собственную реализацию наследуемого инициализатора. Если вы определяете инициализатор с уникальным для суперкласса и подкласса набором входных аргументов, то вы не переопределяете инициализатор, а объявляете новый. Если подкласс имеет хотя бы один собственный инициализатор, то инициализаторы родительского класса не наследуются. **ВНИМАНИЕ** Для вызова инициализатора суперкласса внутри инициализатора субкласса необходимо использовать конструкцию `super.init()`. --- # Переопределение наследуемых свойств Наследуемые свойства иногда ограничивают функциональные возможности субкласса. В таком случае можно переписать геттер или сеттер данного свойства или при необходимости добавить наблюдатель. С помощью механизма переопределения можно расширить наследуемое «только для чтения» свойство до «чтение-запись», реализовав в нем и геттер и сеттер. Но обратное невозможно: если у наследуемого свойства реализованы и геттер и сеттер, нельзя сделать из него свойство «только для чтения». **ВНИМАНИЕ** Хранимые свойства переопределять нельзя, так как вызываемый или наследуемый инициализатор родительского класса попытается установить их значения, но не найдет их. *Сабкласс* не знает деталей реализации наследуемого свойства в суперклассе, он знает лишь имя и тип наследуемого свойства. Поэтому необходимо всегда указывать имя и тип переопределяемого свойства. --- # Модификатор ***final*** Swift позволяет защитить реализацию класса целиком или его отдельных элементов. Для этого необходимо использовать превентивный модификатор `final`, который указывается перед объявлением класса или его отдельных элементов: * ‰‰final class для классов; * ‰‰final var для свойств; * ‰‰final func для методов; При защите реализации класса его наследование в другие классы становится невозможным. Для элементов класса их наследование происходит, но переопределение становится недоступным. --- # Итоги занятия - Разобрали работу с наследованием - Узнали, какой класс считается суперклассом, а какой сабклассом - Изучили переопределение, и как защититься от переопределения --- ## Дополнительные ссылки [rus] https://swiftbook.ru/content/languageguide/inheritance/ [eng] https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html --- # Домашнее задание