2009-06-19 8 views
34

Ich lerne Objective-C und habe einen C/C++ Hintergrund.Wann definiere ich objective-c Methoden?

  • In der objektorientierten C++, müssen Sie immer Ihre Methode erklären, bevor Sie definieren (implementieren) ist es, auch wenn es in der übergeordneten Klasse deklariert wird.

  • Im prozeduralen Stil C, IIRC, können Sie nur eine Funktion definieren, solange sie nur von etwas anderem in derselben Kompilierungseinheit (dh der gleichen Datei) aufgerufen wird, die später in der Datei (naja, vorausgesetzt, Sie geben es nicht an anderer Stelle mit "extern" an).

  • Nun, in Objective-C scheint es, dass Sie nur Selektoren in der Header-Datei deklarieren müssen, wenn sie von etwas extern verwendet werden, und dass Sie Selektoren in Ihrer .m-Datei problemlos erstellen können , und rufen Sie sie in der .m-Datei auf. Offensichtlich werden Delegatmethoden oder geerbte Methoden auch nie (wieder) definiert.

Bin ich auf dem richtigen Weg? Wann müssen Sie in Objective-C einen Selektor definieren?

Antwort

78

Für Objective-C-Methoden besteht die allgemeine Praxis darin, Methoden in den Abschnitt @interface der Header-Datei einzufügen, damit anderer Code nur die .h-Datei enthält und mit Ihrem Code interagieren kann. Auftragsbasierte "faule Deklaration" funktioniert genau wie Funktionen in C - Sie müssen nicht einen Methodenprototyp deklarieren, es sei denn, Sie haben eine Abhängigkeit, die nicht durch Bestellung gelöst werden kann, aber Sie können Methodenprototypen innerhalb der @implementation hinzufügen erforderlich.

Also ja, Sie sind auf dem richtigen Weg. Wiederholen Sie den Methodenprototyp für geerbte Methoden nicht - der Compiler findet ihn in der Headerdatei der Eltern. Delegiertenmethoden können als Prototypen in einer Kategorie definiert (an eine Klasse angeheftet) und wie gewünscht implementiert werden, aber der Delegat muss keinen Methodenprototyp bereitstellen, da er bereits definiert ist. (Es kann immer noch, wenn es für die Klarheit, usw.)

Da Sie gerade Objective-C lernen, ist der Rest dieser Antwort viel mehr Details, als Sie gefragt haben. Du wurdest gewarnt. ;-)


Wenn Sie eine Variable statisch eingeben (zB MyClass* statt id) der Compiler warnt Sie, wenn Sie eine Methode aufrufen versuchen, dass eine Klasse werben nicht, dass es implementiert, ob es funktioniert oder nicht. Wenn Sie die Variable dynamisch eingeben, hält der Compiler Sie nicht davon ab, den gewünschten Aufruf auszuführen, und Sie erhalten nur Laufzeitfehler, wenn Sie etwas aufrufen, das nicht existiert. Was die Sprache betrifft, können Sie jede Methode aufrufen, die eine Klasse zur Laufzeit ohne Fehler implementiert - es gibt keine Möglichkeit, einzuschränken, wer eine Methode aufrufen darf.

Persönlich denke ich, das ist eigentlich eine gute Sache. Wir sind so sehr an die Kapselung und den Schutz unseres Codes aus anderem Code gewöhnt, dass wir den Anrufer manchmal als hinterhältigen Übeltäter und nicht als vertrauenswürdigen Mitarbeiter oder Kunden betrachten. Ich finde es sehr angenehm, mit einer Einstellung von "du machst deinen Job und ich meins" zu kodieren, wo jeder die Grenzen respektiert und sich um sein eigenes Ding kümmert. Man könnte sagen, dass die "Einstellung" von Objective-C eher ein Gemeinschaftsvertrauen als eine strikte Durchsetzung ist. Zum Beispiel bin ich glücklich, jedem zu helfen, der an meinen Schreibtisch kommt, würde aber wirklich genervt sein, wenn jemand mit meinen Sachen herumhantiert oder Dinge herum bewegt, ohne zu fragen. Gut durchdachter Code muss nicht paranoid oder soziopathisch sein, er muss einfach gut zusammenpassen. :-)

Das gibt es viele Ansätze für die Strukturierung Ihrer Schnittstellen, abhängig von der Granularität, die Sie bei der Bereitstellung von Schnittstellen zu Benutzern benötigen. Alle Methoden, die Sie im öffentlichen Header deklarieren, sind im Wesentlichen faires Spiel, das jeder nutzen kann. Das Verstecken von Deklarationen ist ein bisschen so, als würde man Ihr Auto oder Haus verschließen - es wird wahrscheinlich nicht alle draußen halten, aber (1) es "hält ehrliche Leute ehrlich", indem es sie nicht mit etwas verführt, mit dem sie nicht durcheinander kommen sollten, und (2) wer tut bekommen wird sicherlich wissen, dass sie nicht sollten, und kann sich nicht wirklich über negative Folgen beschweren.

Im Folgenden sind einige Konventionen aufgeführt, die ich für die Dateibenennung verwende und was in jeder Datei enthalten ist. Ausgehend von einer .m-Datei am Ende enthält jede Datei die Datei darüber. (Die Verwendung einer strikten Kette von Includes verhindert beispielsweise doppelte Symbolwarnungen.) Einige dieser Ebenen gelten nur für größere wiederverwendbare Komponenten, z. B. Cocoa-Frameworks. Passen Sie sie Ihren Bedürfnissen an und verwenden Sie die Namen, die zu Ihnen passen.

  • MyClass.h - Public API (Application Programming Interface)
  • MyClass_Private.h - Firmenintern SPI (System Programming Interface)
  • MyClass_Internal.h - Projektinterne IPI (Internal Programming Interface)
  • MyClass.m - Umsetzung, allgemein von allen API/SPI/IPI-Deklarationen
  • MyClass_Foo.m - Zusätzliche Implementierung, z. B. für Kategorien

API ist für jedermann zu verwenden, und wird öffentlich unterstützt (normalerweise in Foo.framework/Headers). SPI macht zusätzliche Funktionalität für interne Clients Ihres Codes verfügbar, jedoch unter der Voraussetzung, dass die Unterstützung begrenzt ist und die Schnittstelle Änderungen unterliegt (normalerweise in Foo.framework/PrivateHeaders). IPI besteht aus implementierungsspezifischen Details, die niemals außerhalb des Projekts selbst verwendet werden sollten, und diese Header sind im Framework überhaupt nicht enthalten. Wer sich für SPI- und IPI-Aufrufe entscheidet, tut dies auf eigenes Risiko und normalerweise zu seinem Nachteil, wenn Änderungen den Code sprengen. :-)

+12

+1. Danke, dass Sie darauf hingewiesen haben, dass wir keine Stahlplatten brauchen sollten, damit unsere Kollegen nicht mit unseren Würfeln herumhantieren, und wir sollten keine Sprachdurchsetzung brauchen, um sie davon abzuhalten, mit internen Datenstrukturen zu spielen. Wenn wir beides brauchen, brauchen wir bessere Mitarbeiter. Compiler Warnungen sind wichtig (zusammen mit -Werror), genau wie kleine Etiketten auf Essen im Kühlschrank sagen: "Das ist meins, iss es nicht." ObjC ist eine Sprache für Erwachsene. Sie folgen den Regeln, auch wenn Ihre Mutter (der Compiler) Sie nicht zwingt. Und so müssen Sie keine Tricks um den Compiler finden, wie Sie es oft in anderen Sprachen tun. –

+1

+1 Große Antwort! :) –

+0

Ich hoffe, ich vermisse den Punkt nicht, aber ich habe mich oft gefragt, ob es möglich ist, Member-Variablen mit dieser Struktur von Ebenen-APIs zu verstecken, oder muss noch alles in MyClass.h deklariert werden? – Akusete

6

Die Deklaration der Methoden in der Header-Datei stoppt nur die Compiler-Warnungen. Objective-C ist eine dynamische Sprache. Sie können also eine Methode (eine Nachricht senden) an ein Objekt senden, unabhängig davon, ob diese Methode extern deklariert ist oder nicht.

Wenn Sie eine Methode in der .m-Datei über jedem Code definieren, der sie aufruft (faul deklaration), erzeugt das keine Warnungen. Das Gleiche gilt jedoch, Sie können eine Nachricht an ein Objekt senden, ohne dass es deklariert wird.

Natürlich - das bedeutet, dass es in Objective-C keine privaten Methoden gibt. Jede von einer Klasse implementierte Methode kann aufgerufen werden.

Persönliche Präferenz. Wenn es eine öffentliche Methode ist (d. H. Eine, die extern verwendet wird). deklariere es in der .h und definiere es in der .m. Wenn Sie die Sichtbarkeit einschränken oder zumindest angeben möchten, dass es sich um eine private Methode handelt, verwenden Sie categories/class extensions in der .m-Datei. Obwohl viel Beispielcode die Lazy-Deklarationsmethode verwendet.

3

Objective-C behandelt Funktionen als "Nachrichten" und als solche können Sie eine "Nachricht" an jedes Objekt senden - auch an ein Objekt, das in seiner Schnittstelle nicht explizit angibt, dass es akzeptieren kann. Daher gibt es in Obj-C keine privaten Mitglieder.

Dies kann sehr leistungsfähig sein, ist aber eine Quelle der Verwirrung für neue Obj-C-Programmierer - vor allem solche aus C++, Java oder C#. Hier sind die Grundregeln des Daumens:

  • Sie sollten alle öffentlichen Methoden in Ihrem @ Interface so definieren, dass die Verbraucher wissen, welche Nachrichten Sie erwarten, damit umzugehen.
  • Sie sollten @private-Methoden in Ihrem @interface definieren, um Compiler-Meldungen zu vermeiden und zu vermeiden, dass Sie die Methoden in Ihrer @implementation bestellen müssen.
  • Sie sollten Protokolle verwenden, wenn Sie eine bestimmte Konvention von Methoden für Ihre Klasse implementieren.
  • Vieles davon ist persönliche Vorliebe, aber es hilft, lästige Compiler-Warnungen zu vermeiden und hält Ihren Code organisiert. und leicht zu verstehen.

    +1

    Erläuterung: Das Schlüsselwort "@private" kann nur für Variablendeklarationen verwendet werden, nicht für Methoden. Methoden, die privat sein sollen, können in einer zusätzlichen Headerdatei deklariert werden, die den öffentlichen Header enthält und von der Implementierung (anstelle des öffentlichen Headers) eingeschlossen wird. –