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. :-)
+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 Große Antwort! :) –
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