English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Наследование можно понять как получение класса методов и свойств другого класса.
Когда класс наследует другой класс, класс-наследник называется подклассом, а класс, из которого наследуется, называется суперклассом (или родительским классом)
В Swift класс может вызывать и обращаться к методам, свойствам и индексам суперкласса, а также может перерабатывать их.
Мы также можем добавлять наблюдатели свойств к свойствам, наследованным из класса.
Класс, не наследующий классы других классов, называется базовым классом (Base Class).
В данном примере мы определяем базовый класс StudDetails, описывающий студента (stname) и его оценки по предметам (mark1, mark2, mark3):
class StudDetails { var stname: String! var mark1: Int! var mark2: Int! var mark3: Int! init(stname: String, mark1: Int, mark2: Int, mark3: Int) { self.stname = stname self.mark1 = mark1 self.mark2 = mark2 self.mark3 = mark3 } } let stname = "swift" let mark1 = 98 let mark2 = 89 let mark3 = 76 let sds = StudDetails(stname:stname, mark1:mark1, mark2:mark2, mark3:mark3); print(sds.stname) print(sds.mark1) print(sds.mark2) print(sds.mark3)
Результат выполнения программы приведен выше:
swift 98 89 76
Подкласс指的是 создание нового класса на основе уже существующего класса.
Чтобы указать суперкласс класса, имя суперкласса пишется после имени подкласса, разделенное двоеточием (:), формат грамматики следующий:
class SomeClass: SomeSuperclass { // Определение класса }
В следующем примере мы определяем суперкласс StudDetails, а затем используем подкласс Tom для наследования от него:
class StudDetails { var mark1: Int; var mark2: Int; init(stm1: Int, results stm2: Int) { mark1 = stm1; mark2 = stm2; } func show() { print("Mark1:\(self.mark1), Mark2:\(self.mark2)") } } class Tom: StudDetails { init() { super.init(stm1: 93, results: 89) } } let tom = Tom() tom.show()
Результат выполнения программы приведен выше:
Mark1:93, Mark2:89
Подкласс может реализовать свои пользовательские функции, используя унаследованные методы, классовые методы, примерные свойства или субскриптные скрипты, что мы называем переопределением (overriding).
Мы можем использовать ключевое слово override, чтобы реализовать переопределение.
Вы можете получить доступ к методам, свойствам или субскриптным скриптам суперкласса, используя префикс super.
Переопределение | Доступ к методам, свойствам и субскриптным скриптам |
---|---|
Методы | super.somemethod() |
Свойства | super.someProperty() |
Субскриптный скрипт | super[someIndex] |
В нашем подклассе мы можем использовать ключевое слово override, чтобы переопределить метод суперкласса.
В следующем примере мы переопределяем метод show():
class SuperClass { func show() { print("Это суперкласс SuperClass") } } class SubClass: SuperClass { override func show() { print("Это подкласс SubClass") } } let superClass = SuperClass() superClass.show() let subClass = SubClass() subClass.show()
Результат выполнения программы приведен выше:
Это суперкласс SuperClass Это подкласс SubClass
Вы можете предоставить пользовательские getter (или setter), чтобы переопределить любую унаследованную属性, независимо от того, является ли унаследованная属性 хранимой или вычисляемой.
Подкласс не знает, является ли наследованное свойство инкапсулированным или вычислительным, он знает только, что у наследованного свойства есть имя и тип. Поэтому при перезаписи свойства вы должны указать его имя и тип.
Примечание:
Если вы предоставляете setter в перезаписанном свойстве, то вы также должны предоставить getter.
Если вы не хотите изменять значение наследованного свойства в версии перезаписи getter, вы можете напрямую вернуть наследованное значение, используя super.someProperty, где someProperty - это имя свойства, которое вы хотите перезаписать.
В следующем примере мы определяем суперкласс Circle и подкласс Rectangle, в классе Rectangle мы перезаписываем атрибут area:
class Circle { var radius = 12.5 var area: String { return "Радиус прямоугольника \(radius) " } } // Наследование от суперкласса Circle class Rectangle: Circle { var print = 7 override var area: String { return super.area + " ,но теперь это перезаписано как \(print)" } } let rect = Rectangle() rect.radius = 25.0 rect.print = 3 print("Radius \(rect.area)")
Результат выполнения программы приведен выше:
Радиус прямоугольника 25.0 ,но теперь это перезаписано как 3
Вы можете добавить наблюдатель свойств к инкапсулированному свойству, перезаписанному в наследовании. Таким образом, вы сможете отслеживать, когда изменяется значение наследованного свойства.
Примечание:Вы не можете добавить наблюдатель свойств к инкапсулированным свойствам или только читаемым вычислительным свойствам, наследованным от предка.
class Circle { var radius = 12.5 var area: String { return "Радиус прямоугольника \(radius) " } } class Rectangle: Circle { var print = 7 override var area: String { return super.area + " ,но теперь это перезаписано как \(print)" } } let rect = Rectangle() rect.radius = 25.0 rect.print = 3 print("Радиус: \(rect.area)") class Square: Rectangle { override var radius: Double { didSet {}} print = Int(radius/5.0)+1 } } } let sq = Square() sq.radius = 100.0 print("Радиус: \(sq.area)")
Радиус: Радиус прямоугольника 25.0 ,но теперь это перезаписано как 3 Радиус: Радиус прямоугольника 100.0 ,но теперь это перезаписано как 21
Мы можем использовать ключевое слово final, чтобы предотвратить их перезапись.
Если вы перезапишите final метод, атрибут или индексный скрипт, в процессе компиляции будет выведена ошибка.
Вы можете отметить весь класс как final, добавив финальную характеристику перед ключем class (final class), такой класс не может быть наследован, в противном случае будет выведена компиляционная ошибка.
final class Circle { final var radius = 12.5 var area: String { return "Радиус прямоугольника \(radius) " } } class Rectangle: Circle { var print = 7 override var area: String { return super.area + " ,но теперь это перезаписано как \(print)" } } let rect = Rectangle() rect.radius = 25.0 rect.print = 3 print("Радиус: \(rect.area)") class Square: Rectangle { override var radius: Double { didSet {}} print = Int(radius/5.0)+1 } } } let sq = Square() sq.radius = 100.0 print("Радиус: \(sq.area)")
Поскольку в данном примере используется ключевое слово final, его нельзя перезаписать, поэтому при выполнении возникнет ошибка:
ошибка: var переопределяет 'final' var override var area: String { ^ замечание: перегруженное объявление находится здесь var area: String { ^ ошибка: var переопределяет 'final' var override var radius: Double { ^ замечание: перегруженное объявление находится здесь final var radius = 12.5 ^ ошибка: наследование от класса 'Circle', который является final class Rectangle: Circle { ^