Korrekte init implementierung

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

  • Korrekte init implementierung

    Ich habe inzwischen häufig diese Vorlage für eine init Implementierung gesehen:

    Quellcode

    1. - (id) init {
    2. self = [super init];
    3. if (self != nil) {
    4. // Do some init
    5. }
    6. return self;
    7. }


    Meine Frage ist, muss die Zuweisung an self wirklich sein? Wird nicht etwa self in der Oberklasse initialisiert?
    Meine persönliche Vorlage sieht nun so aus, ohne dass ich aber wirklich abschätzen kann, ob es in allen Situationen korrekt ist.

    Quellcode

    1. - (id) init {
    2. if ([super init]) {
    3. // Do some init
    4. }
    5. return self;
    6. }


    Bisher funktioniert's. Was meint ihr?
  • Was, wenn [super init] aus irgend einem Grund fehl schlägt?
    Dann ist self==nil.

    Was passiert, wenn du jetzt einfach deinen eigenen Setter aufrufen willst?
    [nil setValue:10];

    if() prüft boolsche Werte. Bei [super init] ist das true. Egal was dabei rauskommt. Selbst 'nil' ist was Anderes als false.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • PapaMosh schrieb:

    Meine Frage ist, muss die Zuweisung an self wirklich sein?

    Da gibt es durchaus unterschiedliche Ansichten. Fakt ist, dass init eine andere Instanz als self zurückgeben kann. Daraus ergibt sich, dass Du nicht einfach nur prüfen kannst, ob [super init] nil zurück gibt und wenn nicht, dann ohne weiteres selbst self zurückgeben kannst. Denn dieses self kann dann unter Umständen bereits von super released worden sein und somit Dein Programm in die Knie zwingen.

    Michael
  • Michael schrieb:

    Lucas de Vil schrieb:

    if() prüft boolsche Werte. Bei [super init] ist das true. Egal was dabei rauskommt. Selbst 'nil' ist was Anderes als false.

    Hmm, da muss mein Computer aber verkehrt arbeiten. Der interpretiert nil immer wie false oder NULL oder 0 oder ...

    Michael

    Da hast Du natürlich recht (was Lucas schrieb ist, mE. Quatsch).
    Was bei Dir aber fehlt, ist die Zuweisung self = nil. Ein zusätzliches else { return nil; } wäre entsprechend dann korrekt, aber damit hast Du ja nichtmal Schreibarbeit gespart ;)

    EDIT: Ha! Hast Du ja auch noch extra erklärt. Genau wärend ich das obige schrieb. Das Internet ohne Redundanz passt wahrscheinlich auf eine einzige CD.
    EDIT2: Mhh wenn ich drüber nachdenke, hast Du natürlich noch mehr recht, und mein oben gesagtes ist auch nicht vollkommen richtig. Also dies Post ignorieren :P
    C++
  • Es ist leider etwas komplizierter. if prüft weder auf false, noch auf nil, noch auf NULL, obwohl dann doch wieder.

    Das, was in einer condition steht, ist ein ganz besonderer Datentyp, den es sonst in C nicht gibt. Er hat den Wertebereich { 0, != 0 }, also nur zwei Werte. Dies bedeutet, dass der Compiler stets darauf prüft, ob der Wert dem Wert 0 entspricht – nicht mehr und nicht weniger.

    NULL ist da problematisch. Zeiger haben jede Menge Werte, von denen einer NULL ist. In C ist es nicht garantiert, dass NULL den Wert 0 hat. Das führt dazu, dass eigentlich eine (implizite) Prüfung auf NULL nicht ganz korrekt ist, auch wenn es mutmaßlich sehr wenige Systeme gibt, auf denen NULL nicht 0 ist. Aus diesem Grunde verspricht C, dass NULL in einer Bedingung immer als 0 gewertet wird. Das funktioniert also: NULL ist immer "Bedingung nicht erfüllt".

    nil is ebenfalls nicht { 0, != 0 }. Es behandelt ja Zeiger, die zahlreiche Werte haben können. Daher ist if( self ) eine (Schein-)Gefahr, da es impliziert, dass nil NULL ist. Auf deinem Computer, Michael, mag das so sein, weil nil als 0 versprochen wird. Das ist dokumentiert. Da unter OS X auch NULL 0 ist, kann man sagen, dass nil == NULL und der Vergleich daher zulässig: nil ist immer "Bedingung nicht erfüllt".

    BOOl hat den Wertebereich { NO, YES }. Dies ist nun etwas gänzlich anderes als { 0, !=0 }. Daher ist ein Vergleich auf BOOL ohne "== YES" eigentlich nicht richtig. Aber auch hier verspricht die Dokumentation, dass NO 0 ist und YES verschieden. Da dies kein Zeiger ist, kommt es auf den Wert 0 an. Deshalb funktioniert das durch die Hintertür dann doch wieder sicher: NO ist immer "Bedingung nicht erfüllt".

    Genau genommen wird also in den Fällen implizit ein Cast durchgeführt. Manche schreiben daher "== YES" und "!= nil". Nach der Dokumentation sollte das allerdings nicht notwendig sein. Inhaltlich richtig ist es sicher. "!= NULL" ist indessen ebenso überflüssig (weil ohne auf NULL/!NULL geprüft wird) wie "!= 0" bei Nicht-Zeigern (weil ohnehin auf 0, !0 geprüft wird.) Hier wird etwas sicher gestellt, was der Compiler verspricht.
    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 2 mal editiert, zuletzt von Amin Negm-Awad ()

  • 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.

    Amin Negm-Awad schrieb:


    BOOl hat den Wertebereich { NO, YES }. Dies ist nun etwas gänzlich anderes als { 0, !=0 }. Daher ist ein Vergleich auf BOOL ohne "== YES" eigentlich nicht richtig. Aber auch hier verspricht die Dokumentation, dass NO 0 ist und YES verschieden. Da dies kein Zeiger ist, kommt es auf den Wert 0 an. Deshalb funktioniert das durch die Hintertür dann doch wieder sicher: NO ist immer "Bedingung nicht erfüllt".


    Das ist nicht ganz richtig. BOOL wird per "typedef signed char BOOL" definiert, das heißt der Wertebereich ist größer als nur NO und YES. Das ist übrigens auch in der Objective-C Runtime Reference dokumentiert, genau wie dass NO = 0 und YES = 1 ist. 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.

    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.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von dergraf ()

  • Amin Negm-Awad schrieb:

    nil is ebenfalls nicht { 0, != 0 }. Es behandelt ja Zeiger, die zahlreiche Werte haben können. Daher ist if( self ) eine (Schein-)Gefahr, da es impliziert, dass nil NULL ist. Auf deinem Computer, Michael, mag das so sein, weil nil als 0 versprochen wird. Das ist dokumentiert. Da unter OS X auch NULL 0 ist, kann man sagen, dass nil == NULL und der Vergleich daher zulässig: nil ist immer "Bedingung nicht erfüllt".

    Ich habe nicht ohne Grund das Wort "interpretiert" benutzt. ;)

    Michael
  • Michael schrieb:

    Amin Negm-Awad schrieb:

    nil is ebenfalls nicht { 0, != 0 }. Es behandelt ja Zeiger, die zahlreiche Werte haben können. Daher ist if( self ) eine (Schein-)Gefahr, da es impliziert, dass nil NULL ist. Auf deinem Computer, Michael, mag das so sein, weil nil als 0 versprochen wird. Das ist dokumentiert. Da unter OS X auch NULL 0 ist, kann man sagen, dass nil == NULL und der Vergleich daher zulässig: nil ist immer "Bedingung nicht erfüllt".

    Ich habe nicht ohne Grund das Wort "interpretiert" benutzt. ;)

    Michael


    er meinte auch amin und nicht dich (geh ich mal von aus)
  • gritsch schrieb:

    Michael schrieb:

    Amin Negm-Awad schrieb:

    nil is ebenfalls nicht { 0, != 0 }. Es behandelt ja Zeiger, die zahlreiche Werte haben können. Daher ist if( self ) eine (Schein-)Gefahr, da es impliziert, dass nil NULL ist. Auf deinem Computer, Michael, mag das so sein, weil nil als 0 versprochen wird. Das ist dokumentiert. Da unter OS X auch NULL 0 ist, kann man sagen, dass nil == NULL und der Vergleich daher zulässig: nil ist immer "Bedingung nicht erfüllt".

    Ich habe nicht ohne Grund das Wort "interpretiert" benutzt. ;)

    Michael


    er meinte auch amin und nicht dich (geh ich mal von aus)

    Amin meinte sich selbst? Und nennt dabei explizit meinen Namen?

    Michael
  • dergraf schrieb:

    Amin Negm-Awad schrieb:


    BOOl hat den Wertebereich { NO, YES }. Dies ist nun etwas gänzlich anderes als { 0, !=0 }. Daher ist ein Vergleich auf BOOL ohne "== YES" eigentlich nicht richtig. Aber auch hier verspricht die Dokumentation, dass NO 0 ist und YES verschieden. Da dies kein Zeiger ist, kommt es auf den Wert 0 an. Deshalb funktioniert das durch die Hintertür dann doch wieder sicher: NO ist immer "Bedingung nicht erfüllt".

    Das ist nicht ganz richtig.

    Und wie das ganz richtig ist.
    developer.apple.com/mac/librar…oc/uid/TP30001163-CH3-SW1

    BOOLundefinedA Boolean value, either YES or NO.
    Note that the type of BOOL is char.



    Es wird ganz klipp und klar gesagt: either YES or NO.

    Jede andere Zuweisung an BOOL ist schlicht falsch.

    dergraf schrieb:

    BOOL wird per "typedef signed char BOOL" definiert, das heißt der Wertebereich ist größer als nur NO und YES. Das ist übrigens auch in der Objective-C Runtime Reference dokumentiert, genau wie dass NO = 0 und YES = 1 ist.

    Genau das sagte ich.

    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.

    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.
    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"?
  • Michael schrieb:

    Amin Negm-Awad schrieb:

    nil is ebenfalls nicht { 0, != 0 }. Es behandelt ja Zeiger, die zahlreiche Werte haben können. Daher ist if( self ) eine (Schein-)Gefahr, da es impliziert, dass nil NULL ist. Auf deinem Computer, Michael, mag das so sein, weil nil als 0 versprochen wird. Das ist dokumentiert. Da unter OS X auch NULL 0 ist, kann man sagen, dass nil == NULL und der Vergleich daher zulässig: nil ist immer "Bedingung nicht erfüllt".

    Ich habe nicht ohne Grund das Wort "interpretiert" benutzt. ;)

    Michael
    Okay, war nur ne Klarstellung.

    Ja, ich meinte übrigens dich, als ich "Michael" schrieb. ;)
    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:

    und was hast du dann hier geschrieben?

    Amin Negm-Awad schrieb:

    Aber auch hier verspricht die Dokumentation, dass NO 0 ist und YES verschieden.
    Dass die Dokumentation verspricht, dass NO 0 ist und YES von 0 verschieden. Ich verstehe deine Frage nicht.
    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:

    und was hast du dann hier geschrieben?

    Amin Negm-Awad schrieb:

    Aber auch hier verspricht die Dokumentation, dass NO 0 ist und YES verschieden.
    Dass die Dokumentation verspricht, dass NO 0 ist und YES von 0 verschieden. Ich verstehe deine Frage nicht.


    Und wo verspricht sie dir das? Mir verspricht sie nur dass NO = 0 und YES = 1 (so stehts in der doku und so ist es auch im code). Da steht nirgends was von YES = !NO
  • Ich habe auch nicht YES == !NO gesagt, sondern YES != NO. Und das steht da, weil 0 != 1 ist.

    So schwierg?

    NO == 0;
    YES == 1;
    0 != 1
    Einsetzungsverfahren:
    NO != YES.

    Ich meinte aber ohnehin, dass YES von 0 verschieden ist. Das ergibt sich aber auch daraus
    0 != 1
    Einsetzungsverfahren:
    0 != YES
    YES != 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"?
  • Amin Negm-Awad schrieb:

    Ich habe auch nicht YES == !NO gesagt, sondern YES != NO. Und das steht da, weil 0 != 1 ist.

    So schwierg?

    NO == 0;
    YES == 1;
    0 != 1
    Einsetzungsverfahren:
    NO != YES.

    Ich meinte aber ohnehin, dass YES von 0 verschieden ist. Das ergibt sich aber auch daraus
    0 != 1
    Einsetzungsverfahren:
    0 != YES
    YES != 0


    du hast in deinem beitrag aber nur geschrieben dass NO = 0 und YES ist verschieden von 0.
    Für jeden der nicht weis dass du nur {0, 1} meinst ergibt sich also dass auch 123 YES ist weil es verschieden ist als 0.
    Wenn man nur den wertebereich 0 und 1 hat braucht man ja nicht 0 und verschieden 0 zu sagen sondern einfach nur 0 und 1 oder liebst du es so sehr dich kompliziert auszudrücken dass anfänger es falsch verstehen (siehe 123). Genau du solltest es ja möglichst einfach und verständlich für deine "Kunden" machen oder nicht ;)
  • 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.
    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"?