Korrekte init implementierung

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • gritsch schrieb:

    Amin Negm-Awad schrieb:

    Es ging um das Einsetzen von Bools in eine Condition. Dafür kommt es nur darauf an, dass es verschieden von 0 ist. Ob es 1, 2 oder 123 ist, ist völlig irrelevant. Es ist für meine Kunden nicht einfacher, irrelevante Information zu erhalten.


    du willst ja aber auch nicht dass deine kunden glauben dass (123 == YES) wahr ist?
    Nein, wieso sollten sie das glauben. Die können schließlich lesen. Bisher hat mich jedenfalls noch keiner drauf angesprochen – außer dir, der du das offenkundig nicht richtig gelesen hast.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    gritsch schrieb:

    Amin Negm-Awad schrieb:

    Es ging um das Einsetzen von Bools in eine Condition. Dafür kommt es nur darauf an, dass es verschieden von 0 ist. Ob es 1, 2 oder 123 ist, ist völlig irrelevant. Es ist für meine Kunden nicht einfacher, irrelevante Information zu erhalten.


    du willst ja aber auch nicht dass deine kunden glauben dass (123 == YES) wahr ist?
    Nein, wieso sollten sie das glauben. Die können schließlich lesen. Bisher hat mich jedenfalls noch keiner drauf angesprochen – außer dir, der du das offenkundig nicht richtig gelesen hast.


    na dann ist ja gut...
  • Randbemerkung: Für ein if() ist das alles völlig ohne Belang, der C99 Standard (und somit auch Obj-C, wenn nicht irgendwo das Gegenteil behauptet wird) schreibt eindeutig:
    In both forms, the first substatement is executed if the expression compares unequal to 0.

    Hier gibt es also nur 0 und !=0 :)
    C++
  • zerm schrieb:

    Randbemerkung: Für ein if() ist das alles völlig ohne Belang, der C99 Standard (und somit auch Obj-C, wenn nicht irgendwo das Gegenteil behauptet wird) schreibt eindeutig:
    In both forms, the first substatement is executed if the expression compares unequal to 0.

    Hier gibt es also nur 0 und !=0 :)
    Das hatte ich ja explizit beschrieben. Gritsch hat nur bisher nicht verstanden, dass YES != 0 ausreichend für die Lösung des Problems ist und unterstellt, dass meine Kunden das nicht verstehen. Warum auch immer …
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • gritsch schrieb:

    zerm schrieb:

    Randbemerkung: Für ein if() ist das alles völlig ohne Belang, der C99 Standard (und somit auch Obj-C, wenn nicht irgendwo das Gegenteil behauptet wird) schreibt eindeutig:
    In both forms, the first substatement is executed if the expression compares unequal to 0.

    Hier gibt es also nur 0 und !=0 :)


    das hat ja auch nichts mit == YES zu tun
    Doch, das hat etwas damit zu tun. Einfach noch einmal 10 Beiträge zurück.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • gritsch schrieb:

    Amin Negm-Awad schrieb:

    gritsch schrieb:

    Amin Negm-Awad schrieb:

    Es ging um das Einsetzen von Bools in eine Condition. Dafür kommt es nur darauf an, dass es verschieden von 0 ist. Ob es 1, 2 oder 123 ist, ist völlig irrelevant. Es ist für meine Kunden nicht einfacher, irrelevante Information zu erhalten.


    du willst ja aber auch nicht dass deine kunden glauben dass (123 == YES) wahr ist?
    Nein, wieso sollten sie das glauben. Die können schließlich lesen. Bisher hat mich jedenfalls noch keiner drauf angesprochen – außer dir, der du das offenkundig nicht richtig gelesen hast.


    na dann ist ja gut...
    Ja, du kannst ja nicht unterstellen, dass meine Kunden nicht zwischen notwendiger und hinreichender Bedingung unterscheiden können. Sie müssen das sogar nicht einmal können. Es reicht für die Lösung des Problems aus, dass sie wissen, dass es != 0 ist.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • dergraf schrieb:

    Hier gibt es einen interessanten Artikel zu dem Thema init. Kurz zusammengefasst: In den meisten Fällen ist die Zuweisung an self unnötig, schadet aber auch nicht. Es kommt halt darauf an, was genau super ist.


    Keine AHnung, ob das jetzt an mir lag, dass dieser Teil verschwunden ist.

    Lass es mich so sagen: Shipley zu diesem Thema zu zitieren, ist eine außerordentlich heikle Sache. Zumindest früher hat er behauptet, self = [super init] sei sogar falsch. Als ihm dann das halbe Internet erklärt hat, warum das richtig ist, nahm er das zurück.

    Es ist auch immer noch richtig, es so zu machen: Es ist einfach der Vertrag, der bei -init geschlossen wird. Das kann auch Shipley nicht hinweg denken. Es gibt auch KLassen, die davon explizit Gebrauch machen. IIRC ist etwa -init (NSManagedObject) so ein Kandidat.

    Richtig ist allerdings, dass Shipleys Fehler erstaunlich selten Folgen hat.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Amin Negm-Awad schrieb:

    dergraf schrieb:

    Deswegen sollte man lieber nicht mit == YES vergleichen, sondern mit != NO. Und das kann man sich sparen, da NO = 0 und der Compiler sowieso mit 0 vergleicht.
    Nein, man sollte mit YES vergleichen, weil ein BOOl nur YES und NO beinhalten darf. Wenn da jemand 2 reingestopft hat, dann ist nicht der Vergleich der Fehler, sondern die 2. Man sollte Fehler nicht künstlich heilen, sondern an der Fehlerursache beheben.

    Das ist ja mal ne tolle Einstellung. Somit müsste bei dir ja jede Zuweisung an ein BOOL, wenn es sich nicht explizit um YES oder NO handelt so aussehen:

    Quellcode

    1. if (condition) { boolVar = YES;} else { boolVar = NO;}


    Anders kannst du ja nicht dafür garantieren, dass deine BOOL-Variable nur YES oder NO enthält, wenn du schon nicht an die Garantien von Standard-C glauben willst. Oder willst du auch noch für den Fall vorsorgen, dass Apple eventuell die Werte von YES und NO ändert?

    Amin Negm-Awad schrieb:

    dergraf schrieb:

    Die einfachen Vergleichs-Operatoren liefern zwar immer 0 und 1 zurück, aber ich würde mich nicht darauf verlassen, dass alle Methoden und Funktionen, die ich nicht selber geschrieben habe immer YES für Wahr zurückgeben.
    Die einfachen Vergleichsoperatoren liefern auch nicht immer 0 und 1 zurück. Auf 68k-Systemen, war es etwas ganz üblich, dass -1 geliefert wurde.

    Eine Condition ist einfach etwas anderes als ein BOOL.
    Wenn etwas anderes als 0 oder 1 zurück geliefert wird implementiert der C-Compiler den Standard nicht richtig. Wenn du mir nicht glauben willst, schau im Standard nach, müsste Abschnitt 6.5.8 und 6.5.9 sein. Und wenn wir davon ausgehen, dass das der Fall ist dürfen wir erst recht nicht mit YES oder NO vergleichen oder gar über "richtig" reden.

    Amin Negm-Awad schrieb:


    Lass es mich so sagen: Shipley zu diesem Thema zu zitieren, ist eine außerordentlich heikle Sache. Zumindest früher hat er behauptet, self = [super init] sei sogar falsch. Als ihm dann das halbe Internet erklärt hat, warum das richtig ist, nahm er das zurück.

    Es gibt Fälle da ist self = [super init] wirklich falsch. In den meisten Fällen ist es einfach nur unnötig, schadet aber nicht, schließlich macht -init (NSObject) nichts anderes als "return self". Wenn aber [super init] etwas anderes als nil oder self zurückliefert hat man wirklich ein Problem, wenn einfach self zuweist und so weiter macht als wäre alles in Ordnung. Und ich denke genau das hat er auch gemeint, das einfach so zu machen ohne weiter drüber nachzudenken ist falsch.
  • Meine Güte, eure Condition Diskussion geht aber eigentlich am Thema - das was ich ursprünglich wissen wollte - vorbei.

    Amin Negm-Awad schrieb:

    Es ist auch immer noch richtig, es so zu machen: Es ist einfach der Vertrag, der bei -init geschlossen wird. Das kann auch Shipley nicht hinweg denken. Es gibt auch KLassen, die davon explizit Gebrauch machen. IIRC ist etwa -init (NSManagedObject) so ein Kandidat.


    Das würde mich nun genau interessieren. Was besagt der Vertgrag? Bisher habe ich folgendes Verstanden:
    1. die init Methode initialisiert die Instanzvariablen und liefert den Empfänger, also das initialisierte Objekt zurück.
    2. Es kann sein, dass während der Initialisierung der ursprüngliche Empfänger 'ausgetauscht' wird.
    3. Es kann sein, dass im Rahmen einer Fehlerbehandlung nil zurückgeliefert wird, dem ein [self release] vorangegangen ist.

    Daraus entnehme ich, dass ich im Normalfall (1.) keine Zuweisung brauche. Aber der 2. oder 3. Fall die Zuweisung notwendig macht.
    Nun verstehe ich noch nicht ganz, warum nicht dann in solchen Sonderfällen bereits in der init Methode eine Zuweisung an self erfolgt.

    Beispiel für eine Fehlerbehandlung:

    Quellcode

    1. - (id) init {
    2. if (self = [super init]) {
    3. // Upps - hier gehts nicht weiter
    4. [self release];
    5. self = nil;
    6. }
    7. return self;
    8. }


    Was ist dabei falsch?
  • PapaMosh schrieb:

    Meine Güte, eure Condition Diskussion geht aber eigentlich am Thema - das was ich ursprünglich wissen wollte - vorbei.

    Amin Negm-Awad schrieb:

    Es ist auch immer noch richtig, es so zu machen: Es ist einfach der Vertrag, der bei -init geschlossen wird. Das kann auch Shipley nicht hinweg denken. Es gibt auch KLassen, die davon explizit Gebrauch machen. IIRC ist etwa -init (NSManagedObject) so ein Kandidat.


    Das würde mich nun genau interessieren. Was besagt der Vertgrag? Bisher habe ich folgendes Verstanden:
    1. die init Methode initialisiert die Instanzvariablen und liefert den Empfänger, also das initialisierte Objekt zurück.
    2. Es kann sein, dass während der Initialisierung der ursprüngliche Empfänger 'ausgetauscht' wird.
    3. Es kann sein, dass im Rahmen einer Fehlerbehandlung nil zurückgeliefert wird, dem ein [self release] vorangegangen ist.

    Daraus entnehme ich, dass ich im Normalfall (1.) keine Zuweisung brauche. Aber der 2. oder 3. Fall die Zuweisung notwendig macht.
    Nun verstehe ich noch nicht ganz, warum nicht dann in solchen Sonderfällen bereits in der init Methode eine Zuweisung an self erfolgt.

    Beispiel für eine Fehlerbehandlung:

    Quellcode

    1. - (id) init {
    2. if (self = [super init]) {
    3. // Upps - hier gehts nicht weiter
    4. [self release];
    5. self = nil;
    6. }
    7. return self;
    8. }


    Was ist dabei falsch?
    Ich gehe immer von 2 aus. Egal was Shipley meint. Wer weis was Apple im nächsten Update macht.
    Ob im Fehlerfall ein Release sinnvoll ist wage ich zu bezweifeln.
    Jetzt kann man noch eine Diskussion führen ob man an dieser Stelle nicht eine Exception werfen sollte, habe ich auch mal so gelesen.

    Chris
    Man macht einfach solange irgendwelche Dinge, bis man tot ist.
    Und dann bekommen die anderen Kuchen.
  • PapaMosh schrieb:


    Das würde mich nun genau interessieren. Was besagt der Vertgrag? Bisher habe ich folgendes Verstanden:
    1. die init Methode initialisiert die Instanzvariablen und liefert den Empfänger, also das initialisierte Objekt zurück.
    2. Es kann sein, dass während der Initialisierung der ursprüngliche Empfänger 'ausgetauscht' wird.
    3. Es kann sein, dass im Rahmen einer Fehlerbehandlung nil zurückgeliefert wird, dem ein [self release] vorangegangen ist.

    Daraus entnehme ich, dass ich im Normalfall (1.) keine Zuweisung brauche. Aber der 2. oder 3. Fall die Zuweisung notwendig macht.
    Nun verstehe ich noch nicht ganz, warum nicht dann in solchen Sonderfällen bereits in der init Methode eine Zuweisung an self erfolgt.

    Was ist dabei falsch?
    Dann schauen wir uns doch mal genau an, was init so alles von [super init] zurück bekommen kann:
    1. self
    2. nil
    3. ein anderes Objekt

    Bei 1. und 2. ist eine Zuweisung nicht nötig, sie ändert nichts.
    Bei 3. ist die Zuweisung aber problematisch um nicht falsch zu sagen. Du würdest evtl. versuchen ein Objekt zu initialisieren, dass zu einer anderen Klasse gehört. Im schlimmsten Fall führt das zu einem Programmabsturz wenn du direkt auf iVars zugreifst, die das Objekt gar nicht besitzt. Wenn du die Initialisierung ausschließlich über Setter machst bekommst du ein Exception geworfen, wenn das Objekt das du bekommen hast die verwendeten Selektoren nicht versteht. Kurz, es macht einfach keinen Sinn zu versuchen ein Objekt einer anderen Klasse zu initialisieren. Es gibt einfach keine Lösung die für 100% aller Fälle passt, man muss wissen was man von der Superklasse zu erwarten hat, bevor man eine korrekte eigene init-Methode schreiben kann.

    Chris schrieb:


    Jetzt kann man noch eine Diskussion führen ob man an dieser Stelle nicht eine Exception werfen sollte, habe ich auch mal so gelesen.


    Laut Apples Konvention sollte man nur Exceptions werfen, wenn ein Programmierfehler dafür verantwortlich ist, aber nicht um allgemeine Laufzeitfehler anzuzeigen.
  • dergraf schrieb:

    PapaMosh schrieb:


    Das würde mich nun genau interessieren. Was besagt der Vertgrag? Bisher habe ich folgendes Verstanden:
    1. die init Methode initialisiert die Instanzvariablen und liefert den Empfänger, also das initialisierte Objekt zurück.
    2. Es kann sein, dass während der Initialisierung der ursprüngliche Empfänger 'ausgetauscht' wird.
    3. Es kann sein, dass im Rahmen einer Fehlerbehandlung nil zurückgeliefert wird, dem ein [self release] vorangegangen ist.

    Daraus entnehme ich, dass ich im Normalfall (1.) keine Zuweisung brauche. Aber der 2. oder 3. Fall die Zuweisung notwendig macht.
    Nun verstehe ich noch nicht ganz, warum nicht dann in solchen Sonderfällen bereits in der init Methode eine Zuweisung an self erfolgt.

    Was ist dabei falsch?
    Dann schauen wir uns doch mal genau an, was init so alles von [super init] zurück bekommen kann:
    1. self
    2. nil
    3. ein anderes Objekt

    Bei 1. und 2. ist eine Zuweisung nicht nötig, sie ändert nichts.
    Bei 3. ist die Zuweisung aber problematisch um nicht falsch zu sagen. Du würdest evtl. versuchen ein Objekt zu initialisieren, dass zu einer anderen Klasse gehört. Im schlimmsten Fall führt das zu einem Programmabsturz wenn du direkt auf iVars zugreifst, die das Objekt gar nicht besitzt. Wenn du die Initialisierung ausschließlich über Setter machst bekommst du ein Exception geworfen, wenn das Objekt das du bekommen hast die verwendeten Selektoren nicht versteht. Kurz, es macht einfach keinen Sinn zu versuchen ein Objekt einer anderen Klasse zu initialisieren. Es gibt einfach keine Lösung die für 100% aller Fälle passt, man muss wissen was man von der Superklasse zu erwarten hat, bevor man eine korrekte eigene init-Methode schreiben kann.

    Chris schrieb:


    Jetzt kann man noch eine Diskussion führen ob man an dieser Stelle nicht eine Exception werfen sollte, habe ich auch mal so gelesen.


    Laut Apples Konvention sollte man nur Exceptions werfen, wenn ein Programmierfehler dafür verantwortlich ist, aber nicht um allgemeine Laufzeitfehler anzuzeigen.


    klar machts bei punkt 2 was aus. du bekommst ja nicht mit dass es nil ist wenn dus nicht abfragst!

    punkt 1 ist klar dass self = self; nicht braucht, es schadet aber nicht.

    punkt 3 macht ja wenig sinn.
    In welchem fall sollte eine superklasse im init plötzlich ein komplett anderes objekt zurückgeben.
    Aber wenn dus abfragen willst, kannst dus ja abfragen mit isKindOfClass etc...
  • gritsch schrieb:

    klar machts bei punkt 2 was aus. du bekommst ja nicht mit dass es nil ist wenn dus nicht abfragst!

    Ich hab ja nicht gesagt, dass du das nicht abfragen brauchst. Aber eine Zuweisung an self ist dafür nicht nötig, ein "if (nil == [super init])" reicht dafür vollkommen aus.

    gritsch schrieb:

    punkt 3 macht ja wenig sinn.
    In welchem fall sollte eine superklasse im init plötzlich ein komplett anderes objekt zurückgeben.

    Dafür gibt es viele Beispiele. Man denke an die class cluster wie z.B. NSString, oder an Optimierungen, die manche Klassen durchführen um Speicher zu sparen. Egal wie viele NSNumber-Objekte du mit [[NSNumber alloc] initWithBool: YES] zu erzeugen versuchst, du bekommst immer wieder das selbe Objekt von der Klasse NSCFBoolean geliefert.
  • dergraf schrieb:

    Zitat von »gritsch«



    klar machts bei punkt 2 was aus. du bekommst ja nicht mit dass es nil ist wenn dus nicht abfragst!

    Ich hab ja nicht gesagt, dass du das nicht abfragen brauchst. Aber eine Zuweisung an self ist dafür nicht nötig, ein "if (nil == [super init])" reicht dafür vollkommen aus.


    Zitat von »gritsch«



    punkt 3 macht ja wenig sinn.
    In welchem fall sollte eine superklasse im init plötzlich ein komplett anderes objekt zurückgeben.


    if (nil == [super init]) bringt dir aber keine abkürzung oder sonst irgendwelche vorteile.
    dann ist das so doch schöner und übersichtlicher:

    Quellcode

    1. if ((self = [super init)) { ... } return self;


    dergraf schrieb:

    Dafür gibt es viele Beispiele. Man denke an die class cluster wie z.B. NSString, oder an Optimierungen, die manche Klassen durchführen um Speicher zu sparen. Egal wie viele NSNumber-Objekte du mit [[NSNumber alloc] initWithBool: YES] zu erzeugen versuchst, du bekommst immer wieder das selbe Objekt von der Klasse NSCFBoolean geliefert.


    Dass man Class-cluster nicht subclassen kann sollte das problem doch schon verhindern und wer braucht ne subclass von NSNumber?
  • dergraf schrieb:

    Amin Negm-Awad schrieb:

    dergraf schrieb:

    Deswegen sollte man lieber nicht mit == YES vergleichen, sondern mit != NO. Und das kann man sich sparen, da NO = 0 und der Compiler sowieso mit 0 vergleicht.
    Nein, man sollte mit YES vergleichen, weil ein BOOl nur YES und NO beinhalten darf. Wenn da jemand 2 reingestopft hat, dann ist nicht der Vergleich der Fehler, sondern die 2. Man sollte Fehler nicht künstlich heilen, sondern an der Fehlerursache beheben.

    Das ist ja mal ne tolle Einstellung. Somit müsste bei dir ja jede Zuweisung an ein BOOL, wenn es sich nicht explizit um YES oder NO handelt so aussehen:

    Quellcode

    1. if (condition) { boolVar = YES;} else { boolVar = NO;}



    Nein, es müsste so aussehen:

    Quellcode

    1. boolVar = (cond)?YES:NO;

    Und das findest du in der Tat recht häufig. Und die Leute, bei denen du das findest sind nicht die Schlechtesten.

    dergraf schrieb:

    Anders kannst du ja nicht dafür garantieren, dass deine BOOL-Variable nur YES oder NO enthält, wenn du schon nicht an die Garantien von Standard-C glauben willst. Oder willst du auch noch für den Fall vorsorgen, dass Apple eventuell die Werte von YES und NO ändert?
    Doch, wie bereits gesagt, kann man es garantieren, weil es dokumentiert ist. Aber ohne diese Dokumentation wäre es in der Tat Raten.

    Ich glaube natürlich daran, dass die Doku richtig ist. Klar, es kann sich ändern, dann muss ich meinen Code ändern. Aber das gilt ja für alles.

    dergraf schrieb:

    Amin Negm-Awad schrieb:

    dergraf schrieb:

    Die einfachen Vergleichs-Operatoren liefern zwar immer 0 und 1 zurück, aber ich würde mich nicht darauf verlassen, dass alle Methoden und Funktionen, die ich nicht selber geschrieben habe immer YES für Wahr zurückgeben.
    Die einfachen Vergleichsoperatoren liefern auch nicht immer 0 und 1 zurück. Auf 68k-Systemen, war es etwas ganz üblich, dass -1 geliefert wurde.

    Eine Condition ist einfach etwas anderes als ein BOOL.
    Wenn etwas anderes als 0 oder 1 zurück geliefert wird implementiert der C-Compiler den Standard nicht richtig. Wenn du mir nicht glauben willst, schau im Standard nach, müsste Abschnitt 6.5.8 und 6.5.9 sein. Und wenn wir davon ausgehen, dass das der Fall ist dürfen wir erst recht nicht mit YES oder NO vergleichen oder gar über "richtig" reden.
    Deshalb geht es ja. Das macht es aber nicht richtig.
    Übrigens wäre es klug gewesen, YES einfach als (1 == 1) zu definieren. Dann passiert nie etwas. ABI-Kompatibilität kann natürlich trotzdem flöten gehen.

    dergraf schrieb:

    Amin Negm-Awad schrieb:


    Lass es mich so sagen: Shipley zu diesem Thema zu zitieren, ist eine außerordentlich heikle Sache. Zumindest früher hat er behauptet, self = [super init] sei sogar falsch. Als ihm dann das halbe Internet erklärt hat, warum das richtig ist, nahm er das zurück.

    Es gibt Fälle da ist self = [super init] wirklich falsch. In den meisten Fällen ist es einfach nur unnötig, schadet aber nicht, schließlich macht -init (NSObject) nichts anderes als "return self". Wenn aber [super init] etwas anderes als nil oder self zurückliefert hat man wirklich ein Problem, wenn einfach self zuweist und so weiter macht als wäre alles in Ordnung. Und ich denke genau das hat er auch gemeint, das einfach so zu machen ohne weiter drüber nachzudenken ist falsch.

    Sag mir mal einen Fall. -init…:…: (NSManagedObject) weist etwas anderes zurück. Und nun?


    If you override initWithEntity:insertIntoManagedObjectContext:, you must ensure that you set self to the return value from invocation of super’s implementation, as shown in the following example:


    Es gibt auch Fälle bei den Containern. Und man macht nichts falsch, weil man nicht einfach weiter macht, sondern erst anfängt. Das [super init] ist die erste Nachricht. Es muss mir völlig gleichgültig sein, was -init (super) gemacht hat.

    Nur Shipley weiß das nicht. Und er ist wirklich der einzige.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Amin Negm-Awad ()

  • dergraf schrieb:

    PapaMosh schrieb:


    Das würde mich nun genau interessieren. Was besagt der Vertgrag? Bisher habe ich folgendes Verstanden:
    1. die init Methode initialisiert die Instanzvariablen und liefert den Empfänger, also das initialisierte Objekt zurück.
    2. Es kann sein, dass während der Initialisierung der ursprüngliche Empfänger 'ausgetauscht' wird.
    3. Es kann sein, dass im Rahmen einer Fehlerbehandlung nil zurückgeliefert wird, dem ein [self release] vorangegangen ist.

    Daraus entnehme ich, dass ich im Normalfall (1.) keine Zuweisung brauche. Aber der 2. oder 3. Fall die Zuweisung notwendig macht.
    Nun verstehe ich noch nicht ganz, warum nicht dann in solchen Sonderfällen bereits in der init Methode eine Zuweisung an self erfolgt.

    Was ist dabei falsch?
    Dann schauen wir uns doch mal genau an, was init so alles von [super init] zurück bekommen kann:
    1. self
    2. nil
    3. ein anderes Objekt

    Bei 1. und 2. ist eine Zuweisung nicht nötig, sie ändert nichts.
    Bei 3. ist die Zuweisung aber problematisch um nicht falsch zu sagen. Du würdest evtl. versuchen ein Objekt zu initialisieren, dass zu einer anderen Klasse gehört. Im schlimmsten Fall führt das zu einem Programmabsturz wenn du direkt auf iVars zugreifst, die das Objekt gar nicht besitzt. Wenn du die Initialisierung ausschließlich über Setter machst bekommst du ein Exception geworfen, wenn das Objekt das du bekommen hast die verwendeten Selektoren nicht versteht. Kurz, es macht einfach keinen Sinn zu versuchen ein Objekt einer anderen Klasse zu initialisieren. Es gibt einfach keine Lösung die für 100% aller Fälle passt, man muss wissen was man von der Superklasse zu erwarten hat, bevor man eine korrekte eigene init-Methode schreiben kann.

    Chris schrieb:


    Jetzt kann man noch eine Diskussion führen ob man an dieser Stelle nicht eine Exception werfen sollte, habe ich auch mal so gelesen.


    Laut Apples Konvention sollte man nur Exceptions werfen, wenn ein Programmierfehler dafür verantwortlich ist, aber nicht um allgemeine Laufzeitfehler anzuzeigen.
    Nein, in 3 kann eine andere Instanz derselben Klasse oder einer Subklasse geliefert werden. Es wäre ein Verstoß von -init (super), ein klassenfremde Objekt zu liefern. -init (super) verspricht einfach eine initialisierte Instanz der Klasse – nicht mehr und nicht weniger. Darauf kann ich mich verlassen und das ist okay.

    Und es ist außerordentlich praktisch, die Instanz austauschen zu können. Etwa bei Immutables und bei Twintones. Da kannst du nämlich im +alloc noch nicht feststellen, ob du eine neue Instanz brauchst.Du nennst ja selbst das Beispiel.

    Jetzt mache mal den Twintone. Wie willst du denn in +alloc testen, ob der Twintone schon da ist, wenn du noch gar nicht weißt, was du im initWith…: bekommst?
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • Inzwischen schreibt es Apple auch in der Doku:
    developer.apple.com/mac/librar…c/uid/TP30001163-CH22-SW3

    An init... method normally initializes the instance variables of the receiver, then returns it. It’s the responsibility of the method to return an object that can be used without error.

    Also keine Angst, Bill: Das ist Teil des Vertrages.

    However, in some cases, this responsibility can mean returning a different object than the receiver. For example, if a class keeps a list of named objects, it might provide an initWithName: method to initialize new instances. If there can be no more than one object per name, initWithName: might refuse to assign the same name to two objects. When asked to assign a new instance a name that’s already being used by another object, it might free the newly allocated instance and return the other object—thus ensuring the uniqueness of the name while at the same time providing what was asked for, an instance with the requested name.

    Und auch das ist Teil des Vertrages.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • So lange nicht YES == 0 definiert ist, wird es wohl so sein. CPUs testen ohnehin am liebsten auf 0, != 0.

    Deshalb schrieb ich ja auch schon vor Stunden, dass es darauf ankommt, dass YES != 0 ist. Ob es 1, 5, 9811 oder $wasweißich ist, ist ziemlich gleichgültig. Hauptsache nicht 0.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?