Existe-t-il un moyen standard de créer une "fonction virtuelle pure" dans Swift, c.-à-d. une qui doit doit être remplacée par chaque sous-classe et qui, si ce n’est pas le cas, provoque une erreur de compilation?
Vous avez deux options:
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" (et non une sous-classe réelle) implémente les méthodes requises
Con : La "superclasse" (protocole) ne peut pas implémenter de méthodes ou de propriétés
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 classes abstraites/fonctions virtuelles, mais vous pourriez probablement utiliser un protocole dans 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'
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() { ... }
}
Une autre solution, si vous n'avez pas trop de méthodes "virtuelles", consiste à faire en sorte que la sous-classe transmette les "implémentations" au constructeur de la classe de base en tant qu'objets fonction:
class MyVirtual {
// 'Implementation' provided by subclass
let fooImpl: (() -> String)
// Delegates to 'implementation' provided by subclass
func foo() -> String {
return fooImpl()
}
init(fooImpl: (() -> String)) {
self.fooImpl = fooImpl
}
}
class MyImpl: MyVirtual {
// 'Implementation' for super.foo()
func myFoo() -> String {
return "I am foo"
}
init() {
// pass the 'implementation' to the superclass
super.init(myFoo)
}
}
En tant que nouveau dans le développement iOS, je ne suis pas tout à fait sûr de savoir quand cela a été implémenté, mais un moyen d'obtenir le meilleur des deux mondes consiste à 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 standard fournit toujours une erreur de temps de compilation si elle n'est pas définie