Beim Erstellen von Software ist es hilfreich, eine Vielzahl von Entwurfsprinzipien zu verstehen. Wenn Sie verstehen, wie Sie ein System mit dem am besten geeigneten Prinzip entwerfen, können Sie unzählige Entwicklungsstunden und Kopfschmerzen einsparen.

Lassen Sie uns zuerst ein wenig über Vererbung sprechen. Vererbung ist, wenn eine Klasse den Status und / oder das Verhalten von einer übergeordneten Klasse erbt. Nehmen wir an, wir entwerfen ein Spiel und ich brauche einen Hund:

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

Nach einer Weile stellen wir fest, dass unsere Software, wie alles, Katzen braucht, also erstellen wir eine Katzenklasse:

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

Weil die Natur ruft, fügen wir hinzu .poop() zur Katzen- und Hundeklasse:

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

In diesem Beispiel haben wir zwei Tiere, die kacken können. Leider bieten beide Implementierungen für poop() , daher gibt es hier einige Code-Duplikate. also heben wir an .poop() in eine gemeinsame Tierklasse.

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

Jetzt, da wir überall viele Tiere kacken haben, brauchen wir einen Reinigungsroboter:

CleaningRobot
.drive()
.clean()

Sie brauchen auch einen MurderRobot, der es kann .antrieb() und .töten() die Katzen und Hunde, die sind .poop () ing alle über Ihre weißen Böden:

MurderRobot
.drive()
.kill()

Seit .drive () wird jetzt zwischen CleaningRobot und MurderRobot dupliziert Wir erstellen eine Roboterklasse, um sie einzufügen.

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

So sieht die gesamte Struktur aus:

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

“ Unsere Kunden verlangen einen MurderRobotDog. Es muss dazu in der Lage sein .töten(), .Fahrminuten(), .rinde (), aber es kann nicht kacken ().

Und jetzt sind wir am Arsch. Wir können den MurderRobotDog einfach nicht gut in diese Vererbungshierarchie einpassen. Wir könnten ein neues übergeordnetes Objekt erstellen, in das Sie alle gemeinsam genutzten Funktionen einfügen:

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

Aber das bedeutet, dass Ihre Objekte eine Menge Funktionen haben, die sie nicht verwenden, so dass Sie mit einem Gorilla / Bananen—Problem enden – Sie fordern eine Banane an, aber Sie enden mit einem Gorilla, der die Banane und den ganzen Dschungel damit hält.

Wir können dies jedoch mit Protokollen in Swift modellieren.Wie können Protokolle eine bessere Abstraktion bieten?

Ein Protokoll in Swift definiert Methoden oder Eigenschaften, die eine Klasse dann übernehmen kann. Hier ein Beispiel:

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

Da Klassen mehrere Protokolle übernehmen können. Die MurderRobotDog-Klasse übernimmt das Barker, Killer and driver -Protokoll, was bedeutet, dass die MurderRobotDog-Klasse Implementierungen für bark(), kill(), and clean() bereitstellt.

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

Ab Swift 2.0 können wir jetzt die Codeduplizierung entfernen, indem wir eine Standardimplementierung mithilfe einer Protokollerweiterung bereitstellen:

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

Wir haben uns also ein Beispiel für einen Vererbungsbaum angesehen, der zusammengebrochen ist, und dann untersucht, wie er mithilfe des Protokolls (Schnittstelle) umstrukturiert werden kann.

Die Frage, die Ihnen jetzt wahrscheinlich in den Sinn kommt, lautet: Wann sollten Sie sie verwenden? Nun … die überwiegende Mehrheit der Entwickler ist sich einig, dass wir die Schnittstelle der Vererbung vorziehen sollten. Viele Leute werden Ihnen sagen, dass Sie Vererbung verwenden sollten, wenn etwas eine „ist a“ -Beziehung hat. Zum Beispiel ist Mattias „ein“ Mann, also kann ich Mann erben. Wenn die Beziehung „hat eine“ Natur, wie ein Auto „hat einen“ Motor, dann sollten Sie Zusammensetzung verwenden.

Fazit

Beim Entwurf eines Systems ist es wichtig, das richtige Konstruktionsprinzip für Ihr Modell auszuwählen. In vielen Fällen ist es einfach besser, die Schnittstelle überhaupt zu verwenden. Es ist flexibler, leistungsfähiger und auch sehr einfach zu machen.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.