Wir haben jetzt die "Punkt" -Notation für Eigenschaften. Ich habe verschiedene Hin- und Herbewegungen über die Vorzüge der Punktnotation gegenüber der Nachrichtennotation gesehen. Um die Antworten nicht zu beeinträchtigen, werde ich in der Frage nicht so oder so antworten.
Was halten Sie von der Punktnotation im Vergleich zur Nachrichtennotation für den Zugriff auf Eigenschaften?
Bitte versuchen Sie, es auf Objective-C zu konzentrieren - meine einzige Tendenz, die ich hervorheben werde, ist, dass Objective-C Objective-C ist, sodass Ihre Präferenz, dass es wie Java oder JavaScript ist, nicht gültig ist.
Ein gültiger Kommentar bezieht sich auf technische Probleme (Reihenfolge der Operationen, Priorität der Besetzung, Leistung usw.), Klarheit (Struktur vs. Objektnatur, sowohl für als auch für!), Prägnanz usw.
Beachten Sie, dass ich von der Schule der strengen Qualität und Lesbarkeit von Code bin und an großen Projekten gearbeitet habe, bei denen Codekonvention und -qualität von größter Bedeutung sind (das Schreiben hat einmal tausendmal gelesenes Paradigma).
quelle
Antworten:
Verwenden Sie keinen Punkt für das Verhalten. Verwenden Sie dot, um auf Attribute wie Inhalte zuzugreifen oder diese festzulegen, normalerweise Attribute, die als Eigenschaften deklariert sind.
Für Leute, die neu in Objective-C sind, würde ich empfehlen, den Punkt nur für Dinge zu verwenden, die als @property deklariert sind. Wenn Sie ein Gefühl für die Sprache haben, tun Sie, was sich richtig anfühlt.
Zum Beispiel finde ich Folgendes vollkommen natürlich:
Sie können davon ausgehen, dass der statische Clang-Analysator die Möglichkeit erweitert, zu überprüfen, ob der Punkt nur für bestimmte Muster oder nicht für bestimmte andere Muster verwendet wird.
quelle
.uppercaseString
ob die Klasse ihre Absicht ausdrücken und haben dürfe vom Compiler erzwungen. Vielleicht fehlt mir etwas, das die aktuelle Implementierung der Punktnotation erfordert.@property
aber das würde sowohl erfordern, dass der Verbraucher einer API eine andere boolesche Dimension von Informationen lernt, als auch Entwickler von API in Argumenten darüber ertrinken, was eine sein sollte und was nicht@property
. Beachten Sie, dass Xcode@property
beim Vervollständigen von Code implizite Methoden bevorzugt - stärker gewichtet - . Es wird empfohlen, aber nicht erzwungen.@property
deklarierten Accessoren zu verwenden, wenn die Sprache neu ist. Wenn Sie Vertrauen in die Codierung in Objective-C gewinnen, tun Sie, was sich richtig anfühlt. Interessant; Viele von uns haben sich auf eine sehr, sehr eingeschränkte Verwendung des Punktes beschränkt.Lassen Sie mich zunächst sagen, dass ich mit der Programmierung in Visual / Real Basic begonnen und dann zu Java übergegangen bin, sodass ich die Punktsyntax ziemlich gewohnt bin. Als ich jedoch schließlich zu Objective-C wechselte und mich an Klammern gewöhnte und dann die Einführung von Objective-C 2.0 und seiner Punktsyntax sah, stellte ich fest, dass es mir wirklich nicht gefällt. (Für andere Sprachen ist es in Ordnung, denn so rollen sie).
Ich habe drei Haupt-Beefs mit Punktsyntax in Objective-C:
Rindfleisch Nr. 1: Es macht unklar, warum Sie möglicherweise Fehler erhalten. Zum Beispiel, wenn ich die Zeile habe:
something.frame.origin.x = 42;
Dann erhalte ich einen Compilerfehler, da
something
es sich um ein Objekt handelt und Sie die Strukturen eines Objekts nicht als Wert eines Ausdrucks verwenden können. Wenn ich jedoch:something.frame.origin.x = 42;
Dann wird dies gut kompiliert, da
something
es sich um eine Struktur handelt, die ein NSRect-Mitglied hat, und ich kann sie als Wert verwenden.Wenn ich diesen Code übernehmen würde, müsste ich einige Zeit damit verbringen, herauszufinden, was
something
ist. Ist es eine Struktur? Ist es ein Objekt? Wenn wir jedoch die Klammer-Syntax verwenden, ist es viel klarer:[something setFrame:newFrame];
In diesem Fall gibt es absolut keine Mehrdeutigkeit, ob
something
es sich um ein Objekt handelt oder nicht. Die Einführung von Mehrdeutigkeit ist mein Rindfleisch Nr. 1.Beef # 2: In C wird die Punktsyntax verwendet, um auf Mitglieder von Strukturen zuzugreifen, nicht um Methoden aufzurufen. Programmierer können die
setFoo:
undfoo
Methoden eines Objekts überschreiben und dennoch über auf sie zugreifensomething.foo
. Wenn ich Ausdrücke mit Punktsyntax sehe, erwarte ich, dass sie eine einfache Zuordnung zu einem Ivar darstellen. Dies ist nicht immer der Fall. Stellen Sie sich ein Controller-Objekt vor, das ein Array und eine Tabellenansicht vermittelt. Wenn ich anrufemyController.contentArray = newArray;
, würde ich erwarten, dass das alte Array durch das neue Array ersetzt wird. Der ursprüngliche Programmierer hat jedoch möglicherweise überschrieben,setContentArray:
um nicht nur das Array festzulegen, sondern auch die Tabellenansicht neu zu laden. Aus der Zeile gibt es keinen Hinweis auf dieses Verhalten. Wenn ich sehen würde[myController setContentArray:newArray];
Dann würde ich denken: "Aha, eine Methode. Ich muss mir die Definition dieser Methode ansehen, um sicherzugehen, dass ich weiß, was sie tut."Ich denke, meine Zusammenfassung von Beef # 2 ist, dass Sie die Bedeutung der Punktsyntax mit benutzerdefiniertem Code überschreiben können.
Rindfleisch Nr. 3: Ich denke, es sieht schlecht aus. Als Objective-C-Programmierer bin ich es gewohnt, die Syntax in Klammern zu setzen. Es
foo.name = newName; foo.size = newSize;
ist also ein bisschen ablenkend, mitzulesen und Linien und Linien mit schönen Klammern zu sehen und dann plötzlich mit usw. gebrochen zu werden. Mir ist klar, dass einige Dinge Punktsyntax (C-Strukturen) erfordern, aber das ist das einzige Mal, dass ich sie benutze.Wenn Sie Code für sich selbst schreiben, verwenden Sie natürlich alles, was Sie möchten. Wenn Sie jedoch Code schreiben, den Sie für Open Sourcing planen, oder etwas schreiben, von dem Sie nicht erwarten, dass es für immer beibehalten wird, würde ich die Verwendung der Klammer-Syntax nachdrücklich empfehlen. Dies ist natürlich nur meine Meinung.
Letzter Blog-Beitrag gegen Punktsyntax: http://weblog.bignerdranch.com/?p=83
Gegenargument zum obigen Beitrag: http://eschatologist.net/blog/?p=226 (mit Originalartikel zugunsten der Punktsyntax : http://eschatologist.net/blog/?p=160 )
quelle
something
handelt es sich um ein Objekt, aber ich bin auf einige Stellen gestoßen, an denen die ursprünglichen Autoren Strukturen erstellt haben (für Geschwindigkeit, geringere Speichernutzung usw.), und ich muss ein paar Minuten damit verbringen, herauszufinden, warum der Code nicht funktioniert. t kompilieren.Ich bin ein neuer Cocoa / Objective-C-Entwickler und sehe das folgendermaßen:
Ich halte mich an die Messaging-Notation, obwohl ich mit Obj-C 2.0 angefangen habe und obwohl die Punktnotation ein vertrauteres Gefühl ist (Java ist meine Muttersprache). Mein Grund dafür ist ziemlich einfach: Ich verstehe immer noch nicht genau warum sie der Sprache die Punktnotation hinzugefügt haben. Für mich scheint es eine unnötige, "unreine" Ergänzung zu sein. Wenn jemand erklären kann, wie es der Sprache zugute kommt, würde ich mich freuen, es zu hören.
Ich halte dies jedoch für eine stilistische Wahl, und ich glaube nicht, dass es einen richtigen oder falschen Weg gibt, solange er konsistent und lesbar ist , genau wie bei jeder anderen stilistischen Wahl (z. B. wenn Sie Ihre öffnende geschweifte Klammer auf dieselbe Linie setzen wie den Methodenkopf oder die nächste Zeile).
quelle
Die Objective-C-Punktnotation ist ein syntaktischer Zucker, der in die normale Nachrichtenübermittlung übersetzt wird. Unter der Haube ändert sich also nichts und macht zur Laufzeit keinen Unterschied. Punktnotation ist absolut nicht schneller als das Weiterleiten von Nachrichten.
Danach brauchte ich eine kleine Präambel: Hier sind die Vor- und Nachteile, die ich gesehen habe:
Vor- und Nachteile der Punktnotation
Profis
@property
Notation und der Punktnotation erledigt der Compiler viel Arbeit für Sie. Er kann Code für eine gute Speicherverwaltung beim Abrufen und Festlegen der Eigenschaft generieren. Aus diesem Grund wird die Punktnotation von den offiziellen Leitfäden von Apple selbst vorgeschlagen.Nachteile
@property
Codebeispiele:
(1) Beispiel für einen zusammengesetzten Operator-Verwendungscode:
quelle
Die Verwendung des Stils einer Sprache, der mit der Sprache selbst übereinstimmt, ist hier der beste Rat. Dies ist jedoch kein Fall des Schreibens von Funktionscode in einem OO-System (oder umgekehrt), und die Punktnotation ist Teil der Syntax in Objective-C 2.0.
Jedes System kann missbraucht werden. Die Existenz des Präprozessors in allen C-basierten Sprachen reicht aus, um wirklich seltsame Dinge zu tun. Schauen Sie sich einfach den Obfuscated C Contest an, wenn Sie genau sehen möchten, wie seltsam es werden kann. Bedeutet das, dass der Präprozessor automatisch fehlerhaft ist und Sie ihn niemals verwenden sollten?
Die Verwendung der Punktsyntax für den Zugriff auf Eigenschaften, die in der Benutzeroberfläche als solche definiert wurden, kann missbraucht werden. Die Existenz von Missbrauch in Potentia sollte nicht unbedingt das Argument dagegen sein.
Der Zugang zu Immobilien kann Nebenwirkungen haben. Dies ist orthogonal zu der Syntax, mit der diese Eigenschaft erfasst wird. CoreData, Delegation und dynamische Eigenschaften (first + last = full) erledigen alle Arbeiten im Verborgenen. Dies würde jedoch "Instanzvariablen" mit "Eigenschaften" eines Objekts verwechseln. Es gibt keinen Grund, warum Eigenschaften unbedingt unverändert gespeichert werden müssen, insbesondere wenn sie berechnet werden können (z. B. Länge eines Strings). Unabhängig davon, ob Sie foo.fullName oder [foo fullName] verwenden, wird es immer noch eine dynamische Auswertung geben.
Schließlich wird das Verhalten der Eigenschaft (wenn sie als Wert verwendet wird ) vom Objekt selbst definiert, z. B. ob eine Kopie erstellt oder beibehalten wird. Dies macht es einfacher, das Verhalten später - in der Eigenschaftsdefinition selbst - zu ändern, als Methoden erneut implementieren zu müssen. Dies erhöht die Flexibilität des Ansatzes, was dazu führt, dass weniger (Implementierungs-) Fehler auftreten. Es besteht immer noch die Möglichkeit, die falsche Methode zu wählen (dh kopieren statt beibehalten), aber das ist eher ein Architektur- als ein Implementierungsproblem.
Letztendlich läuft es auf die Frage hinaus, ob es wie eine Struktur aussieht. Dies ist wahrscheinlich das Hauptunterscheidungsmerkmal in den bisherigen Debatten; Wenn Sie eine Struktur haben, funktioniert dies anders als wenn Sie ein Objekt haben. Aber das war schon immer so. Sie können einer Struktur keine Nachricht senden, und Sie müssen wissen, ob sie stapelbasiert oder referenz- / malloc-basiert ist. Es gibt bereits mentale Modelle, die sich in der Verwendung unterscheiden ([[CGRect alloc] init] oder struct CGRect?). Sie waren in Bezug auf das Verhalten nie einheitlich. Sie müssen wissen, womit Sie es jeweils zu tun haben. Es ist sehr unwahrscheinlich, dass das Hinzufügen von Eigenschaftsbezeichnungen für Objekte einen Programmierer verwirrt, der seine Datentypen kennt. und wenn nicht, haben sie größere Probleme.
Was die Konsistenz betrifft; (Ziel-) C ist in sich inkonsistent. = wird sowohl für die Zuweisung als auch für die Gleichheit verwendet, basierend auf der lexikalischen Position im Quellcode. * wird für Zeiger und Multiplikation verwendet. BOOLs sind Zeichen, keine Bytes (oder andere ganzzahlige Werte), obwohl YES und NO 1 bzw. 0 sind. Konsistenz oder Reinheit sind nicht das, wofür die Sprache entwickelt wurde. Es ging darum, Dinge zu erledigen.
Wenn Sie es also nicht verwenden möchten, verwenden Sie es nicht. Mach es anders. Wenn Sie es verwenden möchten und Sie es verstehen, ist es in Ordnung, wenn Sie es verwenden. Andere Sprachen befassen sich mit den Konzepten generischer Datenstrukturen (Maps / Strukturen) und Objekttypen (mit Eigenschaften) und verwenden häufig dieselbe Syntax für beide, obwohl eine lediglich eine Datenstruktur und die andere ein reichhaltiges Objekt ist. Programmierer in Objective-C sollten über die gleiche Fähigkeit verfügen, mit allen Programmierstilen umgehen zu können, auch wenn dies nicht Ihre bevorzugte ist.
quelle
Ich benutze es für Eigenschaften, weil
ist etwas leichter zu lesen als
Im zweiten Fall wird die Lesbarkeit unterbrochen, indem Ihr Gehirn in den Nachrichtensende-Modus versetzt wird, während im ersten Fall klar ist, dass Sie auf die Eigenschaft people des Gruppenobjekts zugreifen.
Ich werde es auch verwenden, wenn ich eine Sammlung ändere, zum Beispiel:
ist etwas lesbarer als
In diesem Fall sollte der Schwerpunkt auf dem Hinzufügen eines Objekts zum Array liegen, anstatt zwei Nachrichten zu verketten.
quelle
Ich bin größtenteils im Objective-C 2.0-Zeitalter aufgewachsen und bevorzuge die Punktnotation. Für mich ermöglicht es die Vereinfachung von Code, anstatt zusätzliche Klammern zu haben, kann ich einfach einen Punkt verwenden.
Ich mag auch die Punktsyntax, weil ich das Gefühl habe, auf eine Eigenschaft des Objekts zuzugreifen, anstatt nur eine Nachricht zu senden (natürlich wird die Punktsyntax wirklich zum Senden von Nachrichten übersetzt, aber aus Gründen des Aussehens fühlt sich der Punkt anders an). Anstatt nach der alten Syntax "einen Getter aufzurufen", fühlt es sich wirklich so an, als würde ich direkt etwas Nützliches aus dem Objekt herausholen.
Ein Teil der Debatte darüber befasst sich mit "Aber wir haben bereits Punktsyntax und es ist für
structs
!". Und das stimmt. Aber (und wieder, das ist nur psychologisch) es fühlt sich für mich im Grunde genauso an. Eine Eigenschaft eines Objekts unter Verwendung von Dot-Syntax Zugriff fühlt das gleiche wie ein Mitglied eines struct zugreifen, die mehr oder weniger die beabsichtigte Wirkung (meiner Meinung) ist.**** Bearbeiten: Wie bbum hervorhob, können Sie auch die Punktsyntax verwenden, um eine beliebige Methode für ein Objekt aufzurufen (das war mir nicht bekannt). Daher werde ich sagen, dass meine Meinung zur Punktsyntax nur für den Umgang mit Eigenschaften eines Objekts gilt, nicht für das tägliche Senden von Nachrichten **
quelle
Ich bevorzuge die Messaging-Syntax sehr ... aber nur, weil ich das gelernt habe. In Anbetracht vieler meiner Klassen und was nicht im Objective-C 1.0-Stil ist, würde ich sie nicht mischen wollen. Ich habe keinen wirklichen Grund außer "was ich gewohnt bin", die Punktsyntax nicht zu verwenden ... AUSSER das macht mich wahnsinnig
Ich weiß nicht warum, aber es macht mich wirklich wütend, ohne guten Grund. Ich denke nur, dass das so ist
ist besser lesbar. Aber jedem sein eigenes!
quelle
[self.title lowercaseString]
oder so. Aber ich kann stilistisch sehen, warum es lästig ist, die Syntax zu mischen und anzupassen. Der einzige Grund, warum ich das mache, ist, klar zu halten, was eine Eigenschaft ist und welche Methode ein Objekt zurückgibt (ich weiß, dass Eigenschaften wirklich genau das sind, aber Sie verstehen hoffentlich, was ich meine).Ehrlich gesagt denke ich, dass es auf den Stil ankommt. Ich persönlich bin gegen die Punktsyntax (insbesondere nachdem ich herausgefunden habe, dass Sie sie für Methodenaufrufe und nicht nur zum Lesen / Schreiben von Variablen verwenden können). Allerdings, wenn Sie gehen , um es zu benutzen, würde ich stark empfehlen nicht verwenden es für etwas anderes als den Zugriff auf und Variablen zu ändern.
quelle
Einer der Hauptvorteile der objektorientierten Programmierung besteht darin, dass kein direkter Zugriff auf den internen Zustand der Objekte besteht.
Die Punktsyntax scheint mir ein Versuch zu sein, sie so aussehen zu lassen, als würde direkt auf den Status zugegriffen. Aber in Wahrheit ist es nur syntaktischer Zucker über die Verhaltensweisen -foo und -setFoo:. Ich selbst nenne einen Spaten lieber einen Spaten. Die Punktsyntax verbessert die Lesbarkeit in dem Maße, in dem der Code prägnanter ist, hilft jedoch nicht beim Verständnis, da nicht berücksichtigt wird, dass Sie wirklich -foo und -setFoo aufrufen: Dies kann zu Problemen führen.
Synthetisierte Accessoren scheinen mir ein Versuch zu sein, das Schreiben von Objekten, auf die direkt zugegriffen wird, zu vereinfachen. Ich glaube, dass dies genau die Art von Programmdesign fördert, die durch objektorientierte Programmierung vermieden wurde.
Alles in allem würde ich lieber Punktsyntax und Eigenschaften nie eingeführt worden. Früher konnte ich den Leuten sagen, dass ObjC ein paar saubere Erweiterungen von C sind, um es Smalltalk ähnlicher zu machen, und ich denke, das stimmt nicht mehr.
quelle
Meiner Meinung nach macht die Punktsyntax Objective-C weniger Smalltalk-artig. Dadurch kann Code einfacher aussehen, es wird jedoch mehrdeutig. Ist es ein
struct
,union
oder ein Objekt?quelle
Viele Leute scheinen 'Eigenschaften' mit 'Instanzvariablen' zu verwechseln. Der Sinn der Eigenschaften besteht darin, es zu ermöglichen, das Objekt zu modifizieren, ohne seine Interna kennen zu müssen, denke ich. Die Instanzvariable ist meistens die 'Implementierung' einer Eigenschaft (die wiederum die 'Schnittstelle' ist), aber nicht immer: Manchmal entspricht eine Eigenschaft nicht einem ivar und berechnet stattdessen einen Rückgabewert. ' on the fly '.
Aus diesem Grund glaube ich, dass die Idee, dass "die Punktsyntax Sie dazu verleitet zu glauben, dass Sie auf die Variable zugreifen, so dass sie verwirrend ist", falsch ist. Punkt oder Klammer, Sie sollten keine Annahmen über die Interna machen: Es ist eine Eigenschaft, kein Ivar.
quelle
->
, der diese Rolle erfüllt (natürlich immer dann, wenn die Ivars nicht auf den Zugriff beschränkt sind).Ich denke, ich könnte zu Messaging anstelle von Punktnotation wechseln, weil in meinem Kopf object.instanceVar nur instanceVar ist , das zum Objekt gehört. Für mich sieht es überhaupt nicht wie ein Methodenaufruf aus , der es ist, also könnte es Dinge geben on in Ihrem Accessor und ob Sie instanceVar oder self.instanceVar verwenden, kann einen viel größeren Unterschied haben als nur implizit oder explizit. Nur meine 2 ¢.
quelle
Die Punktnotation versucht, Nachrichten wie Zugriffe auf ein Mitglied einer Struktur aussehen zu lassen, was sie nicht sind. Könnte in einigen Fällen gut funktionieren. Aber bald wird sich jemand so etwas einfallen lassen:
Sieht gut aus. Ist aber nicht. Es ist das gleiche wie
was nicht funktioniert. Der Compiler akzeptiert den ersten, aber zu Recht nicht den zweiten. Und selbst wenn beim ersten Mal ein Fehler oder eine Warnung ausgegeben wurde, ist dies nur verwirrend.
quelle
Nennen Sie mich faul, aber wenn ich ein einzelnes 'eingeben müsste.' gegen zwei [] jedes Mal, um die gleichen Ergebnisse zu erzielen, würde ich eine einzelne bevorzugen. Ich hasse ausführliche Sprachen. Das () in lisp hat mich verrückt gemacht. Elegante Sprachen wie Mathematik sind prägnant und effektiv, alle anderen sind unzureichend.
quelle
Verwenden Sie die Punktnotation (wann immer Sie können)
Bei Instanzmethoden, die einen Wert zurückgeben
Verwenden Sie keine Punktnotation
Bei Instanzmethoden, die void zurückgeben, bei Init-Methoden oder bei Class-Methoden.
Und meine persönliche Lieblingsausnahme
quelle
Ich persönlich verwende im Code überhaupt keine Punktnotation. Ich verwende es nur bei Bedarf im CoreData KVC-Bindungsausdruck.
Der Grund dafür, dass ich sie nicht im Code verwende, ist, dass die Punktnotation die Setter-Semantik verbirgt. Das Festlegen einer Eigenschaft in Punktnotation sieht unabhängig von der Setter-Semantik (Zuweisen / Beibehalten / Kopieren) immer wie eine Zuweisung aus. Die Verwendung der Nachrichtennotation macht sichtbar, dass das empfangende Objekt die Kontrolle darüber hat, was im Setter geschieht, und unterstreicht die Tatsache, dass diese Effekte berücksichtigt werden müssen.
Ich überlege immer noch, ob ich beim Abrufen des Werts einer KVC-kompatiblen oder deklarierten Eigenschaft möglicherweise die Punktnotation verwenden möchte, da diese zugegebenermaßen etwas kompakter und lesbarer ist und keine versteckte Semantik vorhanden ist. Im Moment bleibe ich aus Gründen der Konsistenz bei der Notation von Nachrichten.
quelle
OK, die Punktnotation in Objective-C sieht in der Tat seltsam aus. Aber ohne das kann ich immer noch nichts machen:
Funktioniert gut, aber:
Gibt mir "Kann nicht in einen Zeigertyp konvertieren". Ich möchte jedoch, dass mein Code mit der Nachrichtennotation übereinstimmt.
quelle
Dies ist eine großartige Frage, und ich sehe viele verschiedene Antworten darauf. Obwohl viele die Themen angesprochen haben, werde ich versuchen, dies aus einem anderen Blickwinkel zu beantworten (einige haben es möglicherweise implizit getan):
Wenn wir die 'Punkt'-Notation verwenden, erfolgt die Auflösung des Ziels für die Methode zur Kompilierungszeit. Wenn wir die Nachrichtenübergabe verwenden, wird die Auflösung des Ziels auf die Laufzeitausführung verschoben. Wenn die Ziele zur Kompilierungszeit aufgelöst werden, ist die Ausführung schneller, da das Auflösen der Ziele zur Laufzeit einige Overheads beinhaltet. (Nicht dass der Zeitunterschied viel ausmachen würde). Da wir die Eigenschaft bereits in der Schnittstelle des Objekts definiert haben, macht es keinen Sinn, die Auflösung des Ziels für eine Eigenschaft zur Laufzeit zu unterscheiden, und daher ist die Punktnotation die Notation, die wir für den Zugriff auf die Eigenschaft verwenden sollten.
quelle