A class can inherit (Inherit) another class's methods (methods), attributes (properties), and other attributes. When a class inherits from another class, the inheriting class is called the subclass (subclass), and the inherited class is called the superclass (or parent class, superclass). In Swift, inheritance is a basic feature of distinguishing between "class" and other types.
In Swift, classes can invoke and access the superclass's methods, properties, and subscript scripts (subscripts), and can override (override) These methods, properties, and subscripts to optimize or modify their behavior. Swift checks to see if your rewrite definition has a matching definition in the superclass to ensure that your rewrite behavior is correct.
Property observers can be added to attributes inherited from a class so that when the property value changes, the class is notified. You can add a property observer for any property, whether it was originally defined as a stored-type property (stored) or a computed property (computed).
Define a base class (base classes)
Classes that do not inherit from other classes are called base classes (base CALSS).
Attention
Classes in Swift are not inherited from a common base class. If you do not specify a superclass for the class you define, the class automatically becomes the base class.
The following example defines a called Vehicle
base class. This base class declares a currentSpeed
stored property named, which is the default value 0.0
(attribute type is inferred as Double
). The currentSpeed
value of the property is used by a String
type of read-only computed property to description
Create a description of the vehicle.
Vehicle
The base class also defines a method named makeNoise
. This method does not actually Vehicle
do anything for the instance, but it will then be Vehicle
customized by the subclass:
class Vehicle { var currentSpeed = 0.0 var description: String { return "traveling at \(currentSpeed) miles per hour" } func makeNoise() { // 什么也不做-因为车辆不一定会有噪音 }}
You can use the initialization syntax to create a Vehicle
new instance of the class name followed by an empty parenthesis:
let someVehicle = Vehicle()
Now that you have created a Vehicle
new instance, you can access its description
properties to print the current speed of the vehicle:
print("Vehicle: \(someVehicle.description)")// Vehicle: traveling at 0.0 miles per hour
Vehicle
class defines a generic feature of a vehicle class, which is actually useless. To make it more useful, you need to refine it to describe a more specific type of vehicle.
Subclass Generation (subclassing)
Subclass Generation (subclassing) refers to the creation of a new class on the basis of an existing class. Subclasses inherit the attributes of the superclass and can be further refined. You can also add new attributes to subclasses.
To indicate a superclass of a class, write the superclass name after the subclass name, separated by a colon:
class SomeClass: SomeSuperclass { // 这里是子类的定义}
In the next example, define a Bicycle
subclass that is called, inheriting into the parent class Vehicle
:
class Bicycle: Vehicle { var hasBasket = false}
The new Bicycle
class automatically obtains Vehicle
all the attributes of the class, such as the currentSpeed
and description
properties, and its makeNoise()
methods.
In addition to the attributes it inherits, the Bicycle
class also defines a false
stored-type property hasBasket
(attribute inference) that is the default value Bool
.
By default, any new instances that you create Bicycle
will not have a basket (that is, the hasBasket
property defaults to false
), and after you create the instance, you can set the properties for a specific Bicycle
instance hasBasket
ture
:
let bicycle = Bicycle()bicycle.hasBasket = true
You can also modify the Bicycle
properties that the instance inherits currentSpeed
, and the properties that the query instance inherits description
:
15.0print("Bicycle: \(bicycle.description)")// Bicycle: traveling at 15.0 miles per hour
Subclasses can also continue to be inherited by other classes, and the following example Bicycle
creates a subclass named Tandem
(two-person bike):
class Tandem: Bicycle { var currentNumberOfPassengers = 0}
Tandem
All properties and methods are inherited from all of the attributes and methods Bicycle
, which in turn inherit all of them Vehicle
. Tandem
also added a new called currentNumberOfPassengers
storage-type attribute, the default value is 0
.
If you create an Tandem
instance, you can use all of its new properties and inherited properties, and you can also query for Vehicle
read-only properties from inheritance description
:
let tandem = Tandem()tandem.hasBasket = truetandem.currentNumberOfPassengers = 2tandem.currentSpeed = 22.0print("Tandem: \(tandem.description)")// Tandem: traveling at 22.0 miles per hour
Rewrite (overriding)
Subclasses can be inherited from instance methods (instance method), class methods, instance properties (instance property), or subscript scripts (subscript) to provide their own customized implementations (implementation). We call this behavior rewriting (overriding).
If you want to override an attribute, you need to precede the rewrite definition with a override
keyword. By doing so, you have shown that you are trying to provide a rewrite version, rather than providing the same definition in the wrong way. Unexpected overrides can cause unpredictable errors, and any overrides that lack a override
keyword are diagnosed as errors at compile time.
override
The keyword reminds the Swift compiler to check if the class's superclass (or one of its parent classes) has a claim that matches the rewritten version. This check will ensure that your rewrite definition is correct.
Methods, properties, and subscript scripts for accessing superclass
When you override a superclass's method, property, or subscript script in a subclass, it is sometimes useful to use an already existing superclass implementation in your rewritten version. For example, you can refine an already implemented behavior, or store a modified value in an inherited variable.
In the right place, you can access the super
superclass version of the method, property, or subscript script by using a prefix:
- In the
someMethod()
overridden implementation of a method, you can super.someMethod()
call the superclass version of the someMethod()
method.
- In the
someProperty
overridden implementation of a property's getter or setter, you can super.someProperty
access the properties of the superclass version someProperty
.
- In the overriding implementation of the subscript script, you can
super[someIndex]
access the same subscript script in the superclass version.
overriding method
In subclasses, you can override an inherited instance method or a class method, providing a custom or alternative method implementation.
The following example defines a Vehicle
new subclass called Train
, which overrides the Vehicle
method inherited from the class makeNoise()
:
class Train: Vehicle { override func makeNoise() { print("Choo Choo") }}
If you create a Train
new instance and call its makeNoise()
method, you will find that Train
the version of the method is called:
let train = Train()train.makeNoise()// 打印 "Choo Choo"
overriding properties
You can override an inherited instance property or Type property, provide your own custom getter and setter, or add a property observer so that overridden properties can observe when a property value changes.
overriding properties of Getters and Setters
You can provide a custom getter (or setter) to override any inherited attribute, regardless of whether the inherited attribute is a stored or computed property. Subclasses do not know whether inherited attributes are stored or computed, and only know that inherited attributes have a name and type. When you rewrite a property, it is necessary to write its name and type. This allows the compiler to check that the property you are overriding matches a property of the same type in the superclass.
You can rewrite an inherited read-only property as a read-write property, just provide the getter and setter in the overridden version's properties. However, you cannot override an inherited read-write property to a read-only property.
Attention
If you provide a setter in the Override property, then you must also provide a getter. If you do not want to modify the inherited property values in the getter in the rewritten version, you can super.someProperty
return the inherited values directly, which is the name of the someProperty
property you want to override.
The following example defines a new class, called Car
, which is a Vehicle
subclass. This class introduces a new storage-type attribute called gear
the default value is an integer 1
. The Car
class overrides the inherited Vehicle
description
property, providing a custom description that contains the current file position:
class Car: Vehicle { var gear = 1 override var description: String { return super.description + " in gear \(gear)" }}
The overridden description
property first calls super.description
Vehicle
the property of the returned class description
. Later, the Car
class version description
adds some extra text at the end to provide information about the current gear.
If you create an Car
instance and set its gear
and currentSpeed
properties, you can see that it description
returns a Car
custom description in:
let car = Car()car.currentSpeed = 25.0car.gear = 3print("Car: \(car.description)")// Car: traveling at 25.0 miles per hour in gear 3
overriding property observers (properties Observer)
You can add property observers to an inherited property by overriding the property. In this way, when the inherited property value changes, you are notified, regardless of how the property was originally implemented. For more information about the property watcher, see Property Watcher.
Attention
You cannot add a property observer for inherited const-stored properties or inherited read-only computed properties. The values of these properties cannot be set, so it is inappropriate to provide them willSet
or didSet
implement them.
Also note that you can not provide both the overridden setter and the overridden property watcher. If you want to observe the change in the property value, and you have provided a custom setter for that property, you can observe any value change in the setter.
The following example defines a new class called AutomaticCar
, which is a Car
subclass. AutomaticCar
means auto-stop, it can automatically select the appropriate gear according to the current speed:
class AutomaticCar: Car { override var currentSpeed: Double { didSet { gear = Int(currentSpeed / 10.0) + 1 } }}
When you set AutomaticCar
the property currentSpeed
, the didSet
observer for the property automatically sets the gear
property, selecting a suitable stop for the new speed. Specifically, the property observer divides the new speed value and then gets the nearest 10
integer value down, and finally the 1
gear
value of the gear. For example, when the speed is 35.0
, the stop is 4
:
let automatic = AutomaticCar()automatic.currentSpeed = 35.0print("AutomaticCar: \(automatic.description)")// AutomaticCar: traveling at 35.0 miles per hour in gear 4
Prevent rewriting
You can prevent them from being overridden by marking final
methods, attributes, or subscript scripts, simply by adding final
modifiers (for example:,, final var
final func
final class func
, and) final subscript
before declaring the keyword.
If you override the final
method, attribute or subscript script, the error will be made at compile time. Methods, properties, or subscript scripts in a class extension can also be marked as final in the definition of an extension.
You can class
final
mark an final class
entire class as final by adding a modifier () before the keyword. Such a class cannot be inherited, and attempting to inherit such a class will result in a compilation error.
Attack on the swift----------inheritance