2010-01-04 4 views
12

I Objective-C für eine Weile verwendet habe, aber von einem statischen Typ Hintergrund (C#) zu sein Ich glaube, ich es verwende in einem sehr statisch. Gegenstände als id zu deklarieren fühlt sich mir fremd an und ich kann nicht sehen, was die Vorteile sind. Kann mir jemand ein Licht scheinen lassen, um es besser zu verstehen?Valorisierung von Objective-C dynamischer Eigenschaften

Antwort

13

Objective-C ist ein bisschen eine Mischsprache, in der Sie als dynamisch sein können und so statisch wie Sie wollen. Sie können alle Typen aller Variablen deklarieren, wenn Sie möchten, können Sie Delegatvariablen sogar als NSObject <Protokoll> * deklarieren, wenn Sie möchten. Der ID-Typ arbeitet weniger als realer Typ und eher wie ein Hinweis für den Compiler, der ihm sagt "Hey, ich weiß, was ich tue, vertraue mir einfach darauf", wodurch der Compiler jegliche Art der Überprüfung dieser bestimmten Variable vermeidet .

Der erste offensichtliche Vorteil des Typs System Objective-C ist, dass Containertypen (NSArray, NSDictionary, NSSet) akzeptieren und ID-Typen zurück. Dies beseitigt die Notwendigkeit für Templates und Generics (wie in C++, Java und C#).

Noch besser ist, können Sie tatsächlich haben Container mit Elementen von jeder innen Art. Solange Sie wissen, was hineingeht, wird sich niemand beschweren, wenn Sie zwei NSStrings, eine NSNumber und einen NSValue innerhalb desselben NSArray hinzufügen. Sie können dies in anderen Sprachen tun, aber Sie müssen die Basisklasse "Object" oder den void * -Typ verwenden und dann müssen Sie Variablen ein- und ausboxen (oder umwandeln und ablegen), um das gleiche Verhalten zu erhalten. In Objective-C ordnest du einfach zu, was das durch Casting-Operatoren und Box-Operationen erzeugte Rauschen beseitigt. Dann können Sie jedem Objekt "responsesToSelector:" oder "class" sagen, um die Identität und die Operationen zu kennen, die Sie zur Laufzeit ausführen können. In Objective-C ist Reflexion ein Bürger erster Klasse.

Ein weiterer Vorteil ist die reduzierte Kompilierzeit; Das Kompilieren eines Objective-C-Programms ist im Allgemeinen viel schneller als das Äquivalent in C++, da nicht so viele Typprüfungen durchgeführt werden und viel zur Laufzeit gemacht wird. Der Compiler vertraut eher dem Programmierer.

Schließlich Objective-C dynamisches Typ-System ermöglicht ein Tool wie Interface Builder zu haben. Dies ist der Hauptgrund, warum Cocoa und Cocoa Touch schnellere Entwicklungszeiten haben; Die GUI kann überall Code mit "ID" -Typen erzeugen, und dies wird deserialisiert, sobald die NIB in den Speicher geladen wird. Die einzige Sprache, die Objective-C hinsichtlich der UI-Design-Erfahrung nahe kommt, ist C# (und natürlich VB.NET), aber um den Preis einer viel schwereren Anwendung.

Ich persönlich bevorzuge es, mit einer mehr statischen Typprüfung zu arbeiten, und ich habe sogar die Einstellung "Behandle Warnungen als Fehler" im Objective-C-Compiler aktiviert; Ich habe einen Blog-Post über sie geschrieben:

http://akosma.com/2009/07/16/objective-c-compiler-warnings/

Dies ist besonders nützlich, wenn Sie mit den Entwicklern arbeiten, die in der Sprache neu sind. Es macht den Compiler häufiger als üblich winseln :)

Statische System-Experten könnten mit all diesen Punkten nicht übereinstimmen, argumentierend, dass die statische Typprüfung "Intellisense" IDEs und bessere Wartung im Allgemeinen erlaubt. Ich habe jahrelang mit .NET gearbeitet (2001 - 2006) und ich muss sagen, dass dynamische Sprachen dazu neigen, weniger Code zu produzieren, einfacher zu lesen sind und generell mehr Freiheiten beim Arbeiten geben. Der Kompromiss (es gibt immer einen Kompromiss) ist, dass zur Kompilierungszeit weniger Informationen vorhanden sind. Aber wie ich neige zu sagen, Compiler sind eine armselige Suite von Tests. Das beste, was IMHO ist, ist eine gute Sammlung von Tests, und eine gute Gruppe von menschlichen Testern quälen Ihren Code, um Fehler zu finden, egal welche Sprache Sie wählen.

+1

Dank @akosma für die Zeit nehmen, um diese ausgezeichnete Antwort zu schreiben. : D –

3

Es ist eher selten, dass Sie ein Objekt als Typ id deklarieren müssen, da Sie im Allgemeinen wissen sollten, welchen Typ Sie erwarten. Manchmal können Sie einen id<Protocol> Typ verwenden, wenn Sie den tatsächlichen Typ eines Objekts nicht kennen, aber wissen, dass es einem bestimmten Protokoll entsprechen sollte.

Gibt es ein bestimmtes Szenario, an das Sie denken?

+0

Ich benutze ID , aber das fühlt sich stark getippt und ist analog zur Verwendung von Schnittstellen in C#. Ich habe gesehen, dass Leute erwähnen, dass einige Aufgaben in dynamischen Sprachen trivial werden, aber sie gaben nie irgendwelche Beispiele. Ich denke, ich möchte nur sicherstellen, dass ich die Sprache voll ausnutze und mir die Dinge nicht schwerer mache, indem ich stark typisiert denke. – Ian1971

2

Passing-Instanz als id ist üblich, wenn Maßnahmen der Methode der Gestaltung; Wenn Sie eine Schaltfläche mit einer Methode verbinden, sieht das Ziel wie folgt aus: doSomething:(id) sender;.

In diesem Fall ermöglicht es verschiedene Arten von Kontrollen der gleichen Aktion Methode zu verwenden, ohne vorherige Kenntnis von dem, was werden diese Kontrollen. Im Methodencode der Aktion können Sie die Klasse des Absenders testen oder einfach über die Eigenschaft tag entscheiden, was zu tun ist.

-(void) doSomething:(id) sender { 
    // Get the sender's tag whatever it is 
    int tag = [sender tag]; 
    switch(tag) { 
     case 1: 
      // ... 
      break; 
     case 2: 
      // ... 
      break; 
    } 
} 
5

Die Dynamik von Objective-C strahlt nicht nur darin, dass jedes Objekt ein id ist. Es glänzt vielmehr mit der Leistungsfähigkeit der Objective-C-Laufzeit und der Benutzerfreundlichkeit. Einige Beispiele für clevere Laufzeitanwendungen von Apple selbst:

DO können Sie ein Proxy-Objekt für ein Obj-C-Objekt in einer separaten App/separaten Maschine einrichten. Dies geschieht, indem alle an das Proxy-Objekt gesendeten Nachrichten abgefangen, zusammengefügt, an die andere App gesendet und dort aufgerufen werden.

KVO wird implementiert, indem die Setter-Methode dynamisch ersetzt wird, sodass die Beobachter automatisch benachrichtigt werden. (Nun, es ist in der Tat subtiler als das ...)

CoreData accessors zur Laufzeit erzeugt werden, für jede Unterklasse von NSManagedObject usw.

Und Sie runtime aus Ihrem Code verwenden können, auch. Ich habe es einmal für einen guten Effekt verwendet, CoreData imitiert und Accessoren zur Laufzeit generiert, und nur ihre Deklaration in der Header-Datei. So können Sie sowohl die statische Typisierung (Kompilierzeitfehler aus der Deklaration im Header) als auch die Dynamik (Laufzeitgenerierung von Methoden) nutzen.

Mike Ash hat eine exzellente Reihe von Blog-Posts geschrieben, die zeigen, wie die Laufzeit funktioniert und wie man sie effektiv einsetzt. Sie müssen es nur lesen! DO, KVO, message forwarding und mehr. Es gibt auch viele andere interessante Beiträge im Netz, wie fun with kvc und übergeordnete Nachrichtenübermittlung 1, 2.

+0

+1 Dies ist eine großartige Sammlung von Links - danke! –