Swift – méthode de classe qui doit être remplacée par la sous-classe

Existe-t-il un moyen standard de créer une “fonction virtuelle pure” dans Swift, c.-à-d. une qui doit être remplacée par chaque sous-classe et qui, si elle ne l’est pas, provoque une erreur de compilation?

Vous avez deux options:

1. Utiliser un protocole

Définir la superclasse en tant que protocole au lieu d’une classe

Pro : vérification du temps de compilation pour savoir si chaque “sous-classe” (pas une sous-classe réelle) implémente la ou les méthodes requirejses

Con : La “superclasse” (protocole) ne peut pas implémenter de méthodes ou de propriétés

2. Affirmer dans la version super de la méthode

Exemple:

 class SuperClass { func someFunc() { fatalError("Must Override") } } class Subclass : SuperClass { override func someFunc() { } } 

Pro : peut implémenter des méthodes et des propriétés dans la superclasse

Con : Pas de vérification du temps de compilation

Il n’y a pas de support pour les fonctions de classe / virtuelles abstraites, mais vous pouvez probablement utiliser un protocole pour la plupart des cas:

 protocol SomeProtocol { func someMethod() } class SomeClass: SomeProtocol { func someMethod() {} } 

Si SomeClass n’implémente pas someMethod, vous obtiendrez cette erreur de compilation:

 error: type 'SomeClass' does not conform to protocol 'SomeProtocol' 

Une autre solution, si vous n’avez pas trop de méthodes “virtuelles”, consiste à faire passer les “implémentations” par la sous-classe dans le constructeur de la classe de base en tant qu’objects fonction:

 class MyVirtual { // 'Implementation' provided by subclass let fooImpl: (() -> Ssortingng) // Delegates to 'implementation' provided by subclass func foo() -> Ssortingng { return fooImpl() } init(fooImpl: (() -> Ssortingng)) { self.fooImpl = fooImpl } } class MyImpl: MyVirtual { // 'Implementation' for super.foo() func myFoo() -> Ssortingng { return "I am foo" } init() { // pass the 'implementation' to the superclass super.init(myFoo) } } 

Ce qui suit permet d’hériter d’une classe et aussi de vérifier le temps de compilation du protocole 🙂

 protocol ViewControllerProtocol { func setupViews() func setupConstraints() } typealias ViewController = ViewControllerClass & ViewControllerProtocol class ViewControllerClass : UIViewController { override func viewDidLoad() { self.setup() } func setup() { guard let controller = self as? ViewController else { return } controller.setupViews() controller.setupConstraints() } //.... and implement methods related to UIViewController at will } class SubClass : ViewController { //-- in case these aren't here... an error will be presented func setupViews() { ... } func setupConstraints() { ... } } 

Étant une nouveauté en matière de développement iOS, je ne suis pas tout à fait sûr de la date de mise en œuvre, mais l’une des façons de tirer le meilleur des deux mondes est d’implémenter une extension pour un protocole:

 protocol ThingsToDo { func doThingOne() } extension ThingsToDo { func doThingTwo() { /* Define code here */} } class Person: ThingsToDo { func doThingOne() { // Already defined in extension doThingTwo() // Rest of code } } 

L’extension est ce qui vous permet d’avoir la valeur par défaut pour une fonction alors que la fonction dans le protocole normal fournit toujours une erreur de compilation si elle n’est pas définie