2

Ich habe eine konzeptionelle Frage Protocol Oriented Programming. Nehmen wir an, ich erstelle ein Protokoll Foo, und ich möchte Foo mit einer Funktion action() in einer Protokollerweiterung erweitern. action() wird immer gleich sein, egal wer gerade implementiert, also möchte ich diesen Code nicht wiederholen müssen. Der einzige Teil von action(), der sich ändert, ist prop, und prop muss eine instance-Eigenschaft sein. Also sollte meine konforme Struktur einfach prop definiert haben, und dann wird die Aktion korrekt funktionieren. Dieser Code ist in Ordnung und sieht wie folgt aus:Swift Protokoll Oriented Mixed Scope

protocol Foo { 
    var prop : String {get set} 
} 
extension Foo { 
    func action() -> String { 
     return prop + ": Applied Action." 
    } 
} 

Aber jetzt hier ist der Haken. Sagen wir, Prop ist eine Information, auf die andere Klassen keinen Zugriff haben sollen. Ich möchte, dass sie nur über action() darauf zugreifen. Im aktuellen swift muss prop mindestens intern sein, da das Protokoll intern ist, aber ich muss es privat haben, so dass konsumierende Klassen nicht versehentlich die Eigenschaft ändern oder Informationen lesen können, die ich nur durch Aktion erhalten möchte() . Ich könnte dem Protokoll action() hinzufügen, aber dann muss ich action() jedes Mal neu schreiben, wenn eine Struktur konform ist.

Das gleiche Beispiel könnte auch auf eine Funktion erweitert:

protocol Foo { 
    //customization point by conforming class 
    func customAction(str: String) -> String 
} 
extension Foo { 
    func action() -> String { 
     //Do some default work 
     let str = "some string created from previous default work" 
     return customAction(str: str) 
    } 
} 

action() wird immer die gleiche Implementierung sein, mit Ausnahme von cusotmAction(). Also brauche ich konforme Klassen, um customAction() zu implementieren, aber ich möchte nicht, dass irgendwelche externen Klassen customAction() aufrufen, da es nur ein bestimmtes Verhalten bietet, das nur innerhalb von action() verwendet werden sollte. Daher muss customAction() privat sein, aber auch dies ist nicht möglich.

Also hier ist meine Frage, ist dies nur eine Aufschlüsselung in Protocol Oriented Programming? Wie kann ich Protokolle verwenden, um diese Art von Code zu schreiben, ohne prop Prop/customAction() zu viel Spielraum zu geben oder denselben Code innerhalb von action() immer wieder neu schreiben zu müssen? Dieses Beispiel ist ziemlich einfach, aber ich stehe vor komplexeren Versionen des gleichen Problems. Gibt es einen anderen Weg, dieses Problem in Bezug auf POP zu betrachten, oder sollte ich einen eher objektorientierten Ansatz betrachten?

Antwort

0

Ich glaube nicht, dass dies ein Rückfall von Protocol-Oriented Programming als ein Konzept ist, sondern nur von der Sprache, in der Sie es verwenden. Vielleicht war Swift nicht auf solche Fälle ausgelegt. Ich denke jedoch, ein Ansatz zur Lösung dieses Problems wäre die Verwendung von Kompositionen, in denen Sie ein Objekt erstellen, für das Funktionen wie action definiert werden sollen, in dem von einem Zustand Gebrauch gemacht wird, der von außen nicht zugänglich ist. Werfen Sie einen Blick auf dieses Beispiel:

struct Foo { 
    init(prop: String) { 
     self.prop = prop 
    } 

    func action() -> String { 
     return prop + ": Applied Action." 
    } 

    private let prop: String 
} 


class Test { 
    let foo = Foo(prop: "TEST") 
} 

In diesem Fall Test kann seine eigenen prop viel in der gleichen Art und Weise (aber nicht genau wie) definieren es wäre, wenn es ein Protokoll verwendet. Davon abgesehen könnten Sie jetzt alle Funktionen auf foo innerhalb einer Instanz von Test aufrufen, ohne Zugriff auf die zugrunde liegenden Variablen zu haben. Wenn Sie so vorgehen (mit Komposition), werden Sie auch von den Vererbungsproblemen befreit, die dazu führen, dass Menschen überhaupt POP verwenden. Ich hoffe das hilft!

+0

Dies scheint eine gute Lösung für die erste Situation, in der es nur eine Variable ist, die angepasst werden muss, aber was ist in der zweiten Situation, in der es eine Funktion ist? Der einzige Weg, um diese Arbeit zu machen, wäre eine Schließung der init? Vielen Dank! –

+1

In Swift können Sie eine Funktion als Variable übergeben und speichern Sie es wie jedes andere Objekt –

+0

Das scheint eine gute mögliche Lösung. Ich bin jedoch interessiert zu wissen, ob es noch mehr POP-Lösungen für dieses Problem gibt. –