Frage

Ich habe gehört, dass, wenn Sie eine Unterklasse haben, sollen Sie die übergeordnete Klasse mit der gleichen Funktion init initialisiert wird innerhalb der init-Unterklasse. Was ich meine ist, dass die init Unterklasse [super init] und Initwithframe [super initwithframe] nennen sollte die Unterklasse nennen sollte. Warum ist das? Warum in einer Endlosschleife der Super init von einer Unterklasse der Initwithframe Ergebnis nennen?

Wenn dies erforderlich ist, dann bedeutet das ich nicht eine neue init-Funktion innerhalb einer Unterklasse wie initWithPoint und habe init oder Initwithframe einfach, weil die Superklasse dieses Anruf Super der nicht über initWithPoint schaffen kann? Ich denke, das Herz der Frage hier einfach ist, warum es unpassend, eine andere Superklasse zu nennen, etwas, das ich vielleicht verwirrend wegen meines c ++ Hintergrund?

War es hilfreich?

Lösung

Wenn Sie eine Unterklasse zu erstellen, wenn Sie einen Initialisierer implementieren, müssen Sie sicher sein, die übergeordnete Klasse der Initialisierer (n) bezeichnet nennen, und Sie müssen mindestens einen Initialisierer der eigenen bezeichneten liefern, obwohl diese nur überschreiben Ihre sein kann die Superklasse.

Als Teil der Unterklasse der Initialisierung, Sie eines der übergeordneten Klasse designierten Initialisierer nennen müssen.

Dokumentation der A-Klasse soll von ihm benannte initializers nominieren. Falls nicht, wird der designierte initializer im Allgemeinen der spezifisch sein initializer (einer nimmt die meisten Argumente) angenommen von der übergeordneten Klasse zur Verfügung gestellt.

Weitere Informationen finden Sie unter "The Objective-C Programmiersprache: Zuordnung und Initialisierung Objekte" [Anmerkung:. Ab Dezember 2013, diese Inhalte nicht mehr verfügbar zu sein scheinen über Apple doc-Center. Was wurde von mehr aufgabenorientierte Tutorials und konzeptioneller Dokumentation ersetzt eine Sprachreferenz ist.]

In Bezug auf Ihre speziellen Fragen:

Warum ist das? Damit die übergeordnete Klasse eine Chance, um seinen Zustand zu initialisieren hat. Sie können dann gehen Sie vor und initialisieren Sie den Zustand, den Sie oben hinzufügen und über das, was die übergeordnete Klasse bietet.

Warum init der Super die von einer Unterklasse ist in einer Endlosschleife Initwithframe Ergebnis nicht nennen? Denn für NSView wird -init nicht der designierte initializer, obwohl es NSObject das ist. So NSView überschreibt er seinen bestimmten Initialisierung, -initWithFrame: zu nennen. Wenn Sie -init von Ihrem -initWithFrame: genannt haben, jetzt haben Sie -initWithFrame: Aufruf -init Aufruf -initWithFrame: Aufruf -init: Aufruf ...

Heißt das ...? Nein, denn dies ist nicht erforderlich. Sie müssen die tatsächliche Dokumentation verstehen, nicht Hörensagen.

Andere Tipps

  

Warum ist das? Warum in einer Endlosschleife der Super init von einer Unterklasse der Initwithframe Ergebnis nennen?

Wenn die -init in Super implementiert als

-(id)init {
  return [self initWithFrame:CGRectZero];
}

dann der Anruf Graph wird Schleife um:

[subclass initWithFrame:]
   |     ^
   v     |
[super init]

als self verwendet immer die aktuelle Klasse ( "Unterklasse").


  

Wenn dies erforderlich ist, dann tut dies, dass ich nicht eine neue init-Funktion innerhalb einer Unterklasse wie initWithPoint und habe einfach init oder Initwithframe dieses Anruf Super der erstellen kann, weil die Superklasse nicht initWithPoint hat?

Nein ist dies nicht erforderlich. Was bevorzugt ist, ist super Die weltweit spezialisiert initializer zu nennen, so gibt es keine -initXXX Anrufe die Chance Super die Unterklasse der -initYYY zurück.

  

Warum wird der init Super Aufruf von einer Initwithframe Ergebnis der Unterklasse in einer Endlos-Schleife?

Ich stammt aus einem C ++ Hintergrund, wie Sie sagen, Sie tun, ist das Hauptproblem wahrscheinlich, dass Sie auf die C ++ Methode ruft Paradigma. In Objective-C, rufen Sie keine Funktionen von Objekten. Es ist nicht einmal technisch völlig richtig Sie invoke Methoden zu sagen. In Objective-C, senden Sie Nachrichten an Objekte und das Objekt entscheidet, was mit ihnen zu tun. Was es normalerweise tut, ist ein Verfahren, in seiner Klasse suchen und aufrufen, die. Die Folge davon ist, dass Sie nicht, welche Version einer Methode in einer Klassenhierarchie steuern können durch eine Meldung aufgerufen wird. Es ist immer die Methode, um die Klasse des Objekts gehört, Sie die Nachricht (außer in einem Fall) zu senden. Es ist, als ob C ++ keine nicht virtuelle Funktionen hatten, nicht einmal die Konstrukteure.

Die einzige Ausnahme ist, wenn Sie eine Nachricht an super schicken. In diesem Fall wird das Verfahren nach Klasse umgangen. Dies kann zu Endlosschleifen führen, wie Sie herausgefunden haben. Der Grund ist, weil wir Funktionen nicht nennen, wir Nachrichten senden. Also, wenn methodA in Klasse SubKlass sendet die Implementierung von methodeB in Klass [super methodB] wird aufgerufen werden. Wenn es dann [self methodA] selbst sendet, ist immer noch eine Instanz von SubKlass, es ist nicht auf magische Weise in eine Instanz von Klass umgewandelt, so methodA in SubKlass wird aufgerufen werden.

Aus diesem Grund scheinen die Regeln für initialisers so gewunden. Nur die angegebene initialiser ist garantiert nicht eine des anderen initialisers zu senden, so können Sie nur sicher die bezeichnete initialiser super in Ihrem initialiser senden.

aus einem c ++ Perspektive:

  

Ich habe gehört, dass, wenn Sie eine Unterklasse haben, sollen Sie die übergeordnete Klasse mit der gleichen Funktion init initialisiert wird innerhalb der init-Unterklasse. Was ich meine ist, dass die init Unterklasse nennen sollte sollte [super initwithframe].

[super init] und der Initwithframe der Unterklasse nennen

das ist nicht wahr. es ist nur gemeinsam. Sie sind frei, jede übergeordnete Klasse nennen initializer dass als gültige initializer dokumentiert ist.

kann es helfen, es wie folgt zu lesen: Blick auf die übergeordnete Klasse initalizers und bestimmen, welche unterstützt werden.

  • manchmal gibt es eine bestimmte Initialisierung
  • manchmal gibt es neue initializers (zum Beispiel eine, die zu dem Super-Super ein Argument hinzufügen kann)
  • manchmal gibt es Initialisierer von der Super-Super geerbt

für bestimmten initializers: halten sie geschützt

für neue initializer: Betrachten Sie es geschützt

für vererbte initializers: Regel entscheiden, ob private, wenn die übergeordnete Klasse neue initializers erklärt, sonst geschützt

  

Warum wird der init Super Aufruf von einer Initwithframe Ergebnis der Unterklasse in einer Endlos-Schleife?

so ist der Effekt (nicht definiertes Verhalten) eines intializer aufrufen, die Sie sollten nicht nennen.

  

Wenn dies erforderlich ist, dann tut dies, dass ich nicht eine neue init-Funktion innerhalb einer Unterklasse wie initWithPoint und habe einfach init oder Initwithframe dieses Anruf Super der erstellen kann, weil die Superklasse nicht initWithPoint hat?

ist dies in Ordnung, solange man durch eine der übergeordneten Klasse initializers unterstützt nennen.

  

ich denke, das Herz der Frage hier einfach ist, warum ist es unangemessen, eine andere Superklasse zu nennen, etwas, das mich vielleicht wegen meiner c ++ Hintergrund ist verwirrend?

objc nicht versteckt / Sichtbarkeit für initializers unterstützen. sobald es in einer Oberklasse -Schnittstelle ist, ist es dort (und Sie sind in der Lage schlechte Entscheidungen zu treffen, wo der Compiler können Ihnen nicht helfen) - Sie erwarten, dass der Sichtbarkeitsgraph für initializers und schreiben Sie Ihre Unterklasse entsprechend zu bestimmen. objc fehlt Sprache verfügt, die Sie mit in c gewöhnt sind ++.

Ich weiß nicht, wo Sie es gehört von, aber AFAIK ist es nicht erforderlich. Sie können Ihre Unterklasse mit init, was Sie wollen, vorausgesetzt, dass Sie ein Init-Methode des übergeordneten Klasse aufrufen. Jede init Methode funktioniert.

Wenn Sie jedoch auch die gleiche Funktion init in der Superklasse haben, denke ich, desto besser, was zu tun ist, diese Funktion aufzurufen, dann Ihre eigene Anpassung hinzuzufügen. Es ist nicht erforderlich, es ist nur eine gute Praxis, dies zu tun, weil die init-Funktion einige Initialisierungen und Einstellungen können vorsehen, dass Sie hinzufügen können vergessen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top