Lors de la création de logiciels, il est utile de comprendre un large éventail de principes de conception. Comprendre comment concevoir un système avec le principe le plus approprié peut économiser d’innombrables heures de développement et de maux de tête.

Parlons d’abord un peu d’héritage. L’héritage est lorsqu’une classe hérite de l’état et / ou du comportement d’une classe parente. Disons que nous concevons un jeu, et j’ai besoin d’un chien:

class Dog {
func bark(){
print("Bark")
}
}

Au bout d’un moment, nous nous rendons compte que notre logiciel, comme tout, a besoin de chats, nous créons donc une classe de chats:

class Cat{
func .meow(){
print("Meow!")
}
}

Parce que la nature appelle, nous ajoutons.caca() à la classe Chat et Chien:

class Dog {
func bark(){
print("Bark")
}
func poop(){
print("Poop")
}
}class cat{
func meow(){
print("Meow")
}
func poop(){
print("Poop")
}
}

Dans cet exemple, nous avons deux animaux capables de faire caca. Malheureusement, ils fournissent tous deux des implémentations pour poop(), il y a donc une duplication de code ici. alors on lève.poop() dans une classe d’animaux partagée.

Animal
.poop()Dog
.bark()Cat
.meow()

Maintenant que nous avons beaucoup d’animaux qui caca partout, nous avons besoin d’un robot de nettoyage:

CleaningRobot
.drive()
.clean()

Vous avez également besoin d’un MurderRobot qui peut.drive() et.tuez () les Chats et les chiens qui le sont.caca () sur tous vos sols blancs:

MurderRobot
.drive()
.kill()

Depuis.drive() est maintenant dupliqué entre CleaningRobot et MurderRobot, nous créons une classe de robots pour le mettre.

Robot
.drive()CleaningRobot
.clean()MurderRobot
.kill()

Voici à quoi ressemble toute la structure:

Robot
.drive()CleaningRobot
.clean()MurderRobot
.kill()Animal
.poop()Dog
.bark()Cat
.meow()

 » Nos clients exigent un MurderRobotDog. Il doit pouvoir le faire.tuer(), .lecteur(), .bark(), mais il ne peut pas faire caca().

Et maintenant, on est foutus. Nous ne pouvons tout simplement pas intégrer le MurderRobotDog dans cette hiérarchie d’héritage. Nous pourrions créer un nouvel objet parent, où vous mettez toutes les fonctionnalités partagées:

GameObject
.bark()Robot
.drive()CleaningRobot
.clean()MurderRobot
.kill()MurderRobotDogAnimal
.poop()DogCat
.meow()

Mais cela signifie que vos objets auront une tonne de fonctionnalités qu’ils n’utilisent pas, vous vous retrouvez donc avec un problème de gorille / Banane — vous demandez une banane, mais vous vous retrouvez avec un gorille tenant la banane et toute la jungle avec elle.

Nous pouvons cependant modéliser cela avec des protocoles dans Swift.Comment les protocoles peuvent-ils fournir une meilleure abstraction ?

Un protocole dans Swift définit des méthodes ou des propriétés qu’une classe peut ensuite adopter. Voici un exemple:

protocol Barker {
func bark()
}
protocol Pooper {
func poop()
}
protocol Driver {
func drive()
}
protocol Cleaner {
func clean()
}
protocol Killer {
func kill()
}

Puisque les classes peuvent adopter plusieurs protocoles. La classe MurderRobotDog adopte le protocole Barker, Killer and driver, ce qui signifie que la classe MurderRobotDog fournit des implémentations pour bark(), kill(), and clean().

class MurderRobotDog: Barker,Killer, Driver{
func bark() {
print("Bark!")
}
func driver() {
print("Drive!")
}
func killer() {
print("Kill!")
}}

Depuis Swift 2.0, nous pouvons maintenant supprimer la duplication de code en fournissant une implémentation par défaut à l’aide d’une extension de protocole:

protocol Barker {
func bark()
}
extension Barker {
func bark() {
print("Bark!")
}
}class Dog: Barker{}
let myDog = Dog()
myDog.bark() // prints "Bark!"

Nous avons donc examiné un exemple d’arbre d’héritage qui s’est effondré, puis nous avons examiné comment le restructurer à l’aide du protocole (interface).

La question qui vous préoccupe probablement maintenant est – quand utiliser chacun d’eux? Eh bien the la grande majorité des développeurs conviennent que nous devrions privilégier l’interface plutôt que l’héritage. Beaucoup de gens vont vous dire que si quelque chose a une relation « est une », alors vous devriez utiliser l’héritage. Par exemple, Mattias « est un » homme, donc je peux hériter de l’homme. Si la relation est de nature « a », comme une voiture « a un » moteur, vous devez utiliser la composition.

Conclusion

Lors de la conception d’un système, il est important de choisir le bon principe de conception pour votre modèle. Dans de nombreuses circonstances, il est juste préférable d’utiliser l’interface en premier lieu. C’est plus flexible, puissant, et c’est aussi très facile à faire.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.