Swift Herencia

Podemos entender la herencia como que una clase obtiene los métodos y las propiedades de otra clase.

Cuando una clase hereda de otra, la clase que hereda se llama subclase, y la clase heredada se llama superclase (o clase padre).

En Swift, una clase puede llamar y acceder a los métodos, propiedades y subíndices de la superclase, y también puede sobrescribirlos.

También podemos añadir observadores de propiedades a las propiedades heredadas por la clase.


Clase base

La clase que no hereda de otras clases se denomina clase base (Base Class).

En el siguiente ejemplo definimos la clase base StudDetails, que describe al estudiante (stname) y las puntuaciones de sus asignaturas (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)

El resultado de ejecutar el programa anterior es:

swift
98
89
76

Subclase

Una subclase se refiere a crear una nueva clase basada en una clase existente.

Para indicar la superclase de una clase, escribe el nombre de la superclase después del nombre de la subclase, separado con dos puntos (:). El formato de sintaxis es el siguiente:

class SomeClass: SomeSuperclass {
    // 类的定义
}

Ejemplo

En el siguiente ejemplo definimos la superclase StudDetails y luego usamos la subclase Tom para heredarla:

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()

El resultado de ejecutar el programa anterior es:

Mark1:93, Mark2:89

Sobrescritura (Overriding)

Una subclase puede implementar su propia funcionalidad personalizada mediante métodos de instancia, métodos de clase, propiedades de instancia o subíndices heredados. A este comportamiento lo llamamos sobrescritura (overriding).

Podemos usar la palabra clave override para implementar la sobrescritura.

Acceso a los métodos, propiedades y subíndices de la superclase

Puedes acceder a los métodos, propiedades o subíndices de la superclase usando el prefijo super.

Sobrescritura Acceso a métodos, propiedades y subíndices
Métodos super.somemethod()
Propiedades super.someProperty()
Subíndices super[someIndex]

Sobrescribir métodos y propiedades

Sobrescribir métodos

En nuestra subclase podemos usar la palabra clave override para sobrescribir los métodos de la superclase.

En el siguiente ejemplo sobrescribimos el método 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()

El resultado de ejecutar el programa anterior es:

这是超类 SuperClass
这是子类 SubClass

Sobrescribir propiedades

Puedes proporcionar un getter (o setter) personalizado para sobrescribir cualquier propiedad heredada, ya sea una propiedad almacenada o una propiedad calculada.

La subclase no sabe si la propiedad heredada es almacenada o calculada; solo sabe que la propiedad heredada tiene un nombre y un tipo. Por lo tanto, al sobrescribir una propiedad, debes escribir tanto su nombre como su tipo.

Puntos a tener en cuenta:

  • Si proporcionas un setter en la propiedad sobrescrita, también debes proporcionar un getter.

  • Si no quieres modificar el valor de la propiedad heredada en el getter de la versión sobrescrita, puedes devolver directamente el valor heredado mediante super.someProperty, donde someProperty es el nombre de la propiedad que quieres sobrescribir.

En el siguiente ejemplo definimos la superclase Circle y la subclase Rectangle; en la clase Rectangle sobrescribimos la propiedad 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)")

El resultado de ejecutar el programa anterior es:

Radius 矩形半径 25.0  ,但现在被重写为 3

Sobrescribir observadores de propiedades

Puedes añadir observadores de propiedades a una propiedad heredada en la sobrescritura de la propiedad. De este modo, cuando el valor de la propiedad heredada cambie, podrás detectarlo.

Nota:No puedes añadir observadores de propiedades a propiedades almacenadas constantes heredadas ni a propiedades calculadas de solo lectura heredadas.

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

Evitar la sobrescritura

Podemos usar la palabra clave final para evitar que se sobrescriban.

Si sobrescribes un método, propiedad o subíndice final, se producirá un error en tiempo de compilación.

Puedes marcar toda la clase como final añadiendo el modificador final (final class) antes de la palabra clave class; de esta manera, la clase no puede ser heredada; de lo contrario, se producirá un error de compilación.

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)")

Como el ejemplo anterior usa la palabra clave final y no permite la sobrescritura, la ejecución dará un error:

error: var overrides a 'final' var
    override var area: String {
                 ^
note: overridden declaration is here
    var area: String {
        ^
error: var overrides a 'final' var
    override var radius: Double {
                 ^
note: overridden declaration is here
    final var radius = 12.5
              ^
error: inheritance from a final class 'Circle'
class Rectangle: Circle {
      ^
Otras extensiones