Warum kann ich das eingelassene Protokoll in Swift nicht verwenden?

77

Ich habe Zweifel an Protokollen in Swift über die Verwendung von var und den Schlüsselwörtern {get set} .

Aus der Apple-Dokumentation :

Wenn ein Protokoll erfordert, dass eine Eigenschaft abrufbar und einstellbar ist, kann diese Eigenschaftsanforderung nicht durch eine konstant gespeicherte Eigenschaft oder eine schreibgeschützte berechnete Eigenschaft erfüllt werden. Wenn das Protokoll nur erfordert, dass eine Eigenschaft abrufbar ist, kann die Anforderung von jeder Art von Eigenschaft erfüllt werden, und es gilt, dass die Eigenschaft auch einstellbar ist, wenn dies für Ihren eigenen Code nützlich ist.

Eigenschaftsanforderungen werden immer als variable Eigenschaften deklariert, denen das Schlüsselwort var vorangestellt ist. Abrufbare und einstellbare Eigenschaften werden durch Schreiben von {get set} nach ihrer Typdeklaration angegeben, und abrufbare Eigenschaften werden durch Schreiben von {get} angegeben.

Ich kann nicht verstehen, warum ich let nicht verwenden kann . Ein var in einem Protokoll mit nur get ist nicht nur ein let ?

Etwas wie das:

protocol someProtocol 
{
   var someProperty: String { get }
}

es wäre nicht nur:

protocol someProtocol 
{
   let someProperty: String
}

Ich vermisse etwas?

Massimo Polimeni
quelle
9
Eine gettable-Eigenschaft kann weiterhin Werte ändern - der Protokollimplementierer kann immer unterschiedliche Werte zurückgeben, der Protokollaufrufer kann sie einfach nicht festlegen. let definiert andererseits eine Konstante. Es kann nur einmal eingestellt werden und darf keinen anderen Wert haben.
pvg
1
@pvg, warum hast du das nicht als Antwort gepostet?
Courteouselk
Ja, das ist hier die richtige Antwort.
sunshinejr
5
@AntonBronnikov Antworten auf einfache Fragen führen oft zu einem Wettbewerb darüber, wer die wortreichste und am wenigsten verständliche Sache eingeben kann. Für kleine Dinge einfacher zu kommentieren. Auch faul.
pvg
@pvg, ich verstehe deinen Standpunkt. Man sollte bitte recht haben.
Courteouselk

Antworten:

63

"Ein var in einem Protokoll mit nur get ist nicht nur ein let?" Nr. A letzeigt eine Konstante an. Dies ist hier jedoch nicht der Fall. Folgendes berücksichtigen:

protocol SomeProtocol {
    var someProperty: String { get }
}

class SomeClass : SomeProtocol {

    var someProperty: String = ""

    func cla () {
        someProperty = "asd"
    }
}

let someInstance = SomeClass()

print(someInstance.someProperty) // outputs ""
someInstance.cla()
print(someInstance.someProperty) // outputs "asd"

Das Protokoll gibt an, was die konforme Klasse nach außen zeigt - eine Eigenschaft des Typs Stringnamens, somePropertydie Sie zumindest erhalten können.

Wenn das Protokoll angibt, kann { get }Ihre Klasse die Konformität über wählen, let someProperty: String = ""aber sie kann auch die Konformität über den obigen Code wählen. Wenn das Protokoll andererseits angibt, dass { get set }Sie es nicht letin der Implementierung verwenden können, sondern es auch einstellbar machen müssen.

Ein Protokoll kann einfach nicht definieren, dass ein Wert konstant sein muss - und sollte es auch nicht sein. Dies ist ein Implementierungsdetail, das von der Klasse / Struktur, die ihn implementiert, berücksichtigt (oder entschieden) werden muss.

luk2302
quelle
Rückblickend war es so einfach und offensichtlich, dass in Protokollen nur Funktionen (dann Eigenschaften) erlaubt sind, aber ich ziehe es immer vor, Zweifel zu stellen und zu lösen; Jetzt ist die Verwendung { get set }klar wie immer, nochmals vielen Dank!
Massimo Polimeni
1
Ein Protokoll kann einfach nicht definieren, dass ein Wert konstant sein muss - und sollte es auch nicht. Warum nicht? Warum hat Apple nicht mehr Granularität bereitgestellt und erlaubt, sowohl let- als auch var-Eigenschaften zu definieren? Oder Sie sagen, Apple hätte sich für das entscheiden können, was ich gesagt habe, stattdessen haben sie sich dafür entschieden, dass die Flexibilität auf Implementierungsebene gegeben werden soll
Honey
45

Der Unterschied ist zwischen

protocol MyProtocol {
    let someProperty: String
}

Das macht keinen Sinn - ein Protokoll soll nicht vorschreiben, wie someProperty es definiert / gespeichert wird , sondern nur, dass es als Eigenschaft verfügbar ist. Es kann sich entweder um eine berechnete oder eine gespeicherte Eigenschaft handeln, aber der Implementierer muss entscheiden, nicht das Protokoll selbst.

und

protocol MyProtocol {
    var someProperty: String { get }  // abstract interface
}

struct MyStruct: MyProtocol {
    let someProperty: String  // concrete implementation: stored property
}

struct OtherStruct: MyProtocol {
    let i: Int
    var someProperty: String { return "\(i)" }  // concrete implementation: computed property
}

das ist durchaus erlaubt!

jtbandes
quelle
1
Ein Protokoll soll nicht vorschreiben, wie somePropertydefiniert / gespeichert wird. Definiert ein Protokoll nicht den Variablennamen / -typ / muss einstellbar sein oder nicht? Warum hat Apple nicht mehr Granularität bereitgestellt und erlaubt, sowohl let- als auch var-Eigenschaften zu definieren?
Honey
2

Ich denke, ein Protokoll kann erfordern, dass eine Struktur etwas hat, aber es kann die Funktionalität von Struktur oder Objekt nicht einschränken. Das sollte Sie nicht daran hindern, das zu tun, was Sie wahrscheinlich im Code tun möchten, beispielsweise die Verwendung von a varim Protokoll und a letfür die Implementierung ist akzeptabel.

protocol MyProtocol {
    var trythis: Int { get }
}

struct MyStructure: MyProtocol {
    let trythis: Int
}
ScottyBlades
quelle