Warum Protokoll ist besser als Klasse in Swift? [geschlossen]

7

Wenn man sich das Video-Tutorial von Apple anschaut, scheint es, dass swift eine protokollorientierte Programmiersprache ist, und Apple ermutigt Programmierer, Protokoll als Klasse zu verwenden. Aber aus meiner persönlichen Sicht sehe ich keine offensichtlichen Vorteile für das Protokoll. Die Klasse kann dem Protokoll entsprechen, aber sie können auch von der Oberklasse erben. Wir können dem Protokoll eine Erweiterung hinzufügen, aber wir können der Klasse auch eine Erweiterung hinzufügen. Wir können Funktionen in Klassen implementieren, die dem Protokoll entsprechen, aber wir können auch func in der Unterklasse überschreiben. Ich bin immer noch verwirrt, warum wir Protokoll statt Klasse verwenden müssen. Und wann sollten wir Protokoll anstelle von Klasse verwenden?

    
beasone 22.03.2016, 04:16
quelle

4 Antworten

6

Nehmen wir ein Download-Beispiel.

Sie haben eine Basisklasse FileDownloadModel und haben 3 Unterklassen AudioFileDownloadModel, VideoFileDownloadModel, ImageDownloadModel .

Sie haben einen DownloadManager , der Eingaben als FileDownloadModel akzeptiert und die urlToDownload -Eigenschaft des Modells zum Herunterladen der Datei verwendet.

Später wird Ihnen gesagt, dass es ein weiteres Modell gibt, aber es kommt wie UserDownloadModel welche Unterklasse von Benutzer .

Sehen Sie, jetzt wird es schwierig, mit einem solchen Szenario fertig zu werden, in dem Sie viel Code ändern müssen, um Download-Methoden einzubinden.

  

Wie Ihnen die protokollorientierte Programmierung hier hilft:

  1. Erstellen Sie ein Protokoll mit dem Namen DownloadingFileProtocol und fügen Sie es hinzu Methoden, die Sie zum Herunterladen der Datei benötigen. z.B. urlToDownload, pathToSave, Erweiterung etc.
  2. Implementieren Sie das gleiche Protokoll in FileDownloadModel und UserDownloadModel Sehen Sie den Vorteil, den Sie nicht ändern müssen Viel Code in UserDownloadModel . Sie werden nur das implementieren Methoden von DownloadingFileProtocol .
  3. Sehen Sie, wenn wieder eine neue Entität auf den Plan tritt, werden Sie nicht Ändern Sie jeden Code nur die Protokollmethoden implementieren.
  4. Und jetzt kann Ihr DownloadManager Eingaben als annehmen DownloadingFileProtocol anstelle eines bestimmten Modells und jetzt können Sie mach irgendein Modell als herunterladbar.
Manoj Aher 22.03.2016, 05:17
quelle
9

Klasse und Protokoll sind orthogonale Konzepte. Ein Protokoll schneidet quer durch den Klassenbaum und verbindet eine oder mehrere Klassen mit einem unterschiedlichen Ursprung.

Vielleicht einfacher gesagt:

  • "class" definiert, was ein Objekt ist.
  • "Protokoll" definiert ein Verhalten, das das Objekt hat.

Sie haben also eine Klasse Auto:

%Vor%

und eine Klasse Color:

%Vor%

Jetzt, mehr oder weniger offensichtlich, Farben und Autos sind völlig unabhängig, aber nehmen wir an, ich möchte in der Lage sein, einfach eins in Strings umzuwandeln, also kann ich debuggen mit:

%Vor%

oder

%Vor%

Genau zu diesem Zweck definiert die Swift-Sprache das Protokoll CustomStringConvertible , so dass wir dann deklarieren können, dass ein Auto unter Verwendung dieses Protokolls gedruckt werden kann:

%Vor%

und eine Farbe auch:

%Vor%

Wo ich vorher eine Druckmethode für jede Klasse gebraucht hätte, brauche ich jetzt nur noch eine Druckmethode, die ungefähr so ​​aussieht:

%Vor%

Dies ist möglich, weil die Deklaration, dass eine Klasse ein Protokoll implementiert, ein Versprechen ist, dass ich die Methoden des Protokolls verwenden kann, in dem Wissen, dass sie implementiert sind und (vermutlich) tun, was erwartet wird.

    
David Berry 22.03.2016 05:38
quelle
2

Hauptsächlich ist es die Hierarchie der Typen. Nehmen wir an, Sie haben ein Objekt, das ein GlowingRedCube darstellt, aber Sie möchten, dass dieser Typ in vielen generischen Code verwendet wird, der Folgendes interessiert:

  • Verschiedene Formen - Cube erweitert Shape
  • Verschiedene Farben - Red erweitert Colorful
  • Unterschiedliche Beleuchtungsart - Glowing erweitert Illuminated

Sie sind in Schwierigkeiten. Du könntest eine Basisklasse wählen und Spezialisierungen hinzufügen: GlowingRedCube erweitert GlowingCube erweitert Shape , aber dann erhältst du eine sehr große Menge von Klassen und eine unflexible Menge von Dingen (was ist, wenn du ein SoftRedCube machen willst) , aber behalten Sie alle Methoden, die Sie für Ihre vorhandene Art von roten Würfel definiert haben?)

Du könntest einfach Cube haben und Illumination und Shape Eigenschaften haben, aber dann bekommst du keine nette Überprüfung des Compilertyps: Wenn du eine Room.lightUp() -Methode hast und ihr eine Cube übergeben musst, dann tust du es muss überprüft werden, ob dieser Typ Beleuchtung enthält! Wenn Sie nur ein Illuminated übergeben könnten, würde der Compiler Sie stoppen, sobald Sie es versucht haben.

Protokolle erlauben Ihnen, dies zu trennen: GlowingRedCube kann das Protokoll Illuminated , das Protokoll Colorful und das Protokoll Shape implementieren. Aufgrund von Protokollerweiterungen können Sie Standardimplementierungen von Funktionen hinzufügen, sodass Sie keine Hierarchieebene zum Anhängen auswählen müssen.

%Vor%

Im Prinzip können Sie mit Protokollen ein Verhalten an ein Objekt anhängen, unabhängig davon, was dieses Objekt sonst noch tut. Das ist genau der Grund, warum sie für Dinge wie Delegate- und Datenquellenprotokolle verwendet werden: Selbst wenn Sie diese Dinge meistens an ein ViewController anhängen, ist das zugrunde liegende Objekt nicht relevant, so dass Sie flexibel bei der Implementierung sein können.

In Swift gibt es viel mehr zu verwenden als nur die Grundlagen: Sie sind außergewöhnlich leistungsfähig, weil sie an verschiedene Code-Konstrukte angehängt werden können: Klassen, Strukturen und Enums. Dies ermöglicht es Ihnen, sich zuerst dem Programmierprotokoll zu nähern. Es gibt ein großartiges Video zu diesem Ansatz von WWDC letztes Jahr , aber es hilft, einige Zeit damit verbracht zu haben, es zu versuchen Einige verschiedene Objekte strukturieren sich zuerst, um ein Gefühl für die Probleme zu bekommen.

    
Ian Barber 22.03.2016 05:38
quelle
1

Bei Protokollen kann eine Klasse / Struktur als verschiedene Dinge verwendet werden. Zum Beispiel entspricht die String struct soooo vielen Protokollen!

%Vor%

Dies bedeutet, dass String als 11 verschiedene Dinge verwendet werden können! Wenn eine Methode eines der obigen Protokolle als Parameter benötigt, können Sie eine Zeichenfolge übergeben.

"Aber ich kann einfach eine Gottklasse erstellen, die alle Methoden hat, die die Protokolle haben!" du hast gestritten. Denken Sie daran, dass Sie in Swift nur von einer einzigen Klasse erben können, und die Mehrfachvererbung ist nur so gefährlich, dass sie Ihren Code super komplex machen kann.

Außerdem können Sie mit Protokollen Ihr benutzerdefiniertes Verhalten der Klasse definieren. String s hashcode Methode ist nicht identisch mit der von Int . Aber sie sind beide mit dieser Funktion kompatibel:

%Vor%

Das ist das wahre Wunder der Protokolle.

Nicht zuletzt machen Protokolle Sinn . Protokolle repräsentieren eine Beziehung "ist eine Art von" oder "kann als verwendet werden". Wenn X als Y verwendet werden kann, macht es Sinn, dass X dem Protokoll Y entspricht, richtig?

    
Sweeper 22.03.2016 05:16
quelle

Tags und Links