Héritage Swift

L'héritage peut être compris comme une classe acquérant les méthodes et propriétés d'une autre classe.

Lorsqu'une classe hérite d'une autre classe, la classe qui hérite est appelée sous-classe, et la classe héritée est appelée superclasse (ou classe parente).

En Swift, une classe peut appeler et accéder aux méthodes, propriétés et indices de la superclasse, et peut les redéfinir.

Nous pouvons également ajouter des observateurs de propriété aux propriétés héritées par une classe.


Classe de base

Une classe qui n'hérite d'aucune autre classe est appelée classe de base.

Dans l'exemple suivant, nous définissons une classe de base StudDetails, qui décrit un étudiant (stname) et ses notes dans diverses matières (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)

La sortie de l'exécution du programme ci-dessus est :

swift
98
89
76

Sous-classe

Une sous-classe désigne la création d'une nouvelle classe basée sur une classe existante.

Pour indiquer la superclasse d'une classe, écrivez le nom de la superclasse après le nom de la sous-classe, séparés par deux-points (:). Le format de syntaxe est le suivant :

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

Exemples

Dans l'exemple suivant, nous définissons une superclasse StudDetails, puis nous utilisons une sous-classe Tom pour en hériter :

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

La sortie de l'exécution du programme ci-dessus est :

Mark1:93, Mark2:89

Redéfinition

Une sous-classe peut implémenter sa propre fonctionnalité personnalisée via des méthodes d'instance, des méthodes de classe, des propriétés d'instance ou des indices hérités. Nous appelons ce comportement la redéfinition.

Nous pouvons utiliser le mot-clé override pour implémenter la redéfinition.

Accès aux méthodes, propriétés et indices de la superclasse

Vous pouvez accéder aux méthodes, propriétés ou indices de la superclasse en utilisant le préfixe super.

Redéfinition Accès aux méthodes, propriétés et indices
Méthodes super.somemethod()
Propriétés super.someProperty()
Indices super[someIndex]

Redéfinition des méthodes et propriétés

Redéfinition de méthodes

Dans notre sous-classe, nous pouvons utiliser le mot-clé override pour redéfinir les méthodes de la superclasse.

Dans l'exemple suivant, nous redéfinissons la méthode 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()

La sortie de l'exécution du programme ci-dessus est :

这是超类 SuperClass
这是子类 SubClass

Redéfinition de propriétés

Vous pouvez fournir un getter (ou un setter) personnalisé pour redéfinir toute propriété héritée, que la propriété héritée soit stockée ou calculée.

La sous-classe ne sait pas si la propriété héritée est stockée ou calculée ; elle sait seulement que la propriété héritée a un nom et un type. Ainsi, lorsque vous redéfinissez une propriété, vous devez spécifier à la fois son nom et son type.

Notes :

  • Si vous fournissez un setter dans la propriété redéfinie, vous devez également fournir un getter.

  • Si vous ne voulez pas modifier la valeur de la propriété héritée dans le getter de la version redéfinie, vous pouvez renvoyer directement la valeur héritée via super.someProperty, où someProperty est le nom de la propriété que vous redéfinissez.

Dans l'exemple suivant, nous définissons une superclasse Circle et une sous-classe Rectangle. Dans la classe Rectangle, nous redéfinissons la propriété 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)")

La sortie de l'exécution du programme ci-dessus est :

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

Redéfinition des observateurs de propriété

Vous pouvez ajouter des observateurs de propriété à une propriété héritée dans une redéfinition de propriété. De cette façon, vous pouvez surveiller le moment où la valeur de la propriété héritée change.

Remarque :Vous ne pouvez pas ajouter d'observateurs de propriété à des propriétés stockées constantes héritées ni à des propriétés calculées en lecture seule héritées.

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

Empêcher les redéfinitions

Nous pouvons utiliser le mot-clé final pour empêcher leur redéfinition.

Si vous redéfinissez une méthode, une propriété ou un subscript final, une erreur de compilation se produira.

Vous pouvez marquer une classe entière comme final en ajoutant le modificateur final (final class) avant le mot-clé class. Une telle classe ne peut pas être héritée ; sinon, une erreur de compilation se produira.

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

Étant donné que l'exemple ci-dessus utilise le mot-clé final et n'autorise pas la redéfinition, l'exécution entraînera une erreur :

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 {
      ^
Autres extensions