(Anfänger)Frage zu Objektiv-C

anhe

Aktives Mitglied
Thread Starter
Dabei seit
13.11.2007
Beiträge
1.899
Reaktionspunkte
309
Hallo zusammen,

ich lerne gerade nach dem Buch "Programming in Objective-C" von Stephen G. Kochan (6. Auflage). Momentan befasse ich mich im Kapitel 11 mit Protokollen, das ist aber hier nicht direkt das Problem. Ich komme mit einer Methode die ich als Lösung einer Aufgabe geschrieben habe nicht weiter. Ich habe hierzu das folgende Minimalbeispiel geschrieben:

Code:
#import <Foundation/Foundation.h>

@interface Fraction : NSObject

@property int numerator, denominator;

-(void) setTo: (int) n over: (int) d;
-(Fraction *) initWith: (int) n over: (int) d;
-(BOOL) isEqualTo:(id) object;
-(BOOL) isEqualTo2:(Fraction *) f;

@end

@implementation Fraction

@synthesize numerator, denominator;

-(void) setTo:(int)n over:(int)d
{
    numerator = n;
    denominator = d;
}

-(Fraction *) initWith:(int)n over:(int)d
{
    self = [super init];

    if (self)
        [self setTo: n over:d];

    return self;
}

-(BOOL) isEqualTo:(id)object
{

    BOOL isEqual = NO;
    //NSLog(@"%@",[object class]);

    if (self == object)
        isEqual = YES;

    return isEqual;
}

-(BOOL) isEqualTo2:(id)object
{
    BOOL isEqual = NO;

    if ([self numerator]==[object numerator] && [self denominator] == [object denominator]) {
        isEqual = YES;
    }

    return isEqual;
}


@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
    
        Fraction *a, *b;
    
        a = [[Fraction alloc] initWith:3 over:5];
        b = [[Fraction alloc] initWith:3 over:5];
    
    
        if ([a isEqualTo:b]) {
            NSLog(@"Fraction a is equal to fraction b");
        }
        else
            NSLog(@"No, Fraction a is not equal to fraction b");
    
        NSLog(@"%i", [a isEqualTo:b]);
        NSLog(@"%i", [a isEqualTo:a]);
        NSLog(@"%i", [a isEqualTo2:b]);
    }
    return 0;
}

Code:
No, Fraction a is not equal to fraction b
0
1
1
Das Problem liegt in der Methode "-(BOOL) isEqualTo: (id) object". Leider liefert [a isEqualTo:b] nicht Yes bzw. 1 als Antwort, obwohl ich beiden Instanzen die gleichen Werte als Variablen zugewiesen habe. Einzig [a isEqualTo:a] liefert YES als Antwort. Prüft "(self == object) ob es exakt die gleichen Speicherbereiche sind und nicht die eingetragenen Werte identisch sind? Die Zuweisung von (id) object als Instanz von "Fraktion" funktioniert. Das habe ich mit [object class] überprüft.

Die Methode "-(BOOL) isEqualTo2:(id) object" vergleicht die Instanzvariablen direkt und funktioniert wie sie soll auch für zwei nichtidentische Instanzen deren Variablen die gleichen Werte haben.

Über ein paar erklärende Worte würde ich mich sehr freuen.

Viele Grüße

André
 
ich verstehe nicht so ganz was du machen willst, du vergleichst da object IDs?
du erzeugst da zwei instanzen, die haben unterschiedliche IDs, die sind nicht gleich, auch wenn du da gleiche werte rein packst.

du müsstest also eher die werte, die drin stehen vergleichen, statt der object ID .
 
Hallo oneOeight,

dann habe ich den "id"Datentyp bisher noch nicht korrekt verstanden. Ich habe das im Buch so verstanden, dass der id-Datentyp ein generischer "object-typ" ist der Objekte verschiedener Klassen enthalten kann. Im meinem Fall enthält der id-type mit Namen object eine Instanz des Objektes Fraction. Vielleicht ist die Bezeichnung "object" etwas unglücklich aber so war es auch in der Aufgabe gefordert...

Viele Grüße

André
 
Alles klar, dann verstehe ich das. Dann kann es also auch nur ein "identisch oder nicht" geben? Ein "größer" oder "kleiner" erscheint nicht sinnvoll, da es unabhängig von den Werten der Instanzvariablen ist. Ist das korrekt?

Viele Grüße

André
 
Ja. Wäre da nicht eine Runtime und virtuelle Speicherverwaltung dazwischen, wäre das wohl eine existente Speicheradresse, von der du keine relevante Aussage ableiten kannst (außer bei bestimmten Situationen in z.B. Arrays).
Im Grunde hast du eine Prüfung auf Namensgleichheit gemacht, während du Strukturgleichheit wolltest.
 
Hallo Kaito,

danke für Deine Nachricht.
(...)während du Strukturgleichheit wolltest.

ja, jetzt erscheint mir das auch logisch. Ich habe diese und weitere Methoden jetzt umgesetzt in dem ich die einzelnen Variablen miteinander vergleiche.

Viele Grüße

André
 
Hallo André,

Problem ist soweit klar…

Aber als Anfänger möchte ich Dir gleich ein paar Ratschläge mit auf den Weg geben. Wahrscheinlich bist Du bei Java ode so zuhause und da nimmt man es nicht so streng :D
Gewöhne Dir ab der ersten Minute an sauberen Code zu schreiben.

a.)
Deine Klassen sollte mit einem Präfix versehen werden.
"MYPerson", "MYVehicle" etc. Apple gehört "NS" und Du machst Dein Eigenes.

b.)
Gewöhne Dir nicht nicht diese Mischmasch-Schreibweise ohne Klammern beim if-else-an.
Klammere immer! Das ist nur Gewohnheit und spart keine Zeit, wenn man sie weglässt.
Spart aber endlos Zeit beim Fehlersuchen, weil man dort eben nicht suchen muss.

c.)
Keine if-Bedingungen mit unzähliger UND-ODER-Verschachtelung.
Gewöhne Dir Return-Early an. Zumal der Code in den meisten Fällen performanter wird.

d.)
Prüfe Parameter gegen nil bzw. wenn zu erwarten NULL!
Bestes Beispiel, dass viele Programmierer da draussen immer wieder rotieren lässt.
[array addObject:eek:bject] … das kracht. Viele Apple-Methoden behandeln keine nil-Parameter und es ist Deine Pflicht.

Nur schon mal um ein paar Gedanken zu machen…

Viele Grüße
 
Und das Wichtigste vergessen :D

Es wird großen Wert auf selbsterklärende Methoden-, Parameternamen etc. gelegt.
Der Quelltext sollte "sprechend" sein. Parameter mit "a" oder so nennen ist nicht.
Wörter/Benennungen werden konsequent ausgeschrieben.

Viele Grüße
 
Hallo little_pixel,

vielen Dank für Deine Antwort und Deine Ratschläge.

(...)Wahrscheinlich bist Du bei Java ode so zuhause (...)

Da überschätzt Du mich offenbar maßlos. Das was ich beruflich auswerte muss mache ich mit Matlab. "Programmieren" lernen mache ich nur zum Spaß. Ich habe das immer wieder mal angefangen, aber diesmal bin ich zuversichtlich ...

(...)
"MYPerson", "MYVehicle" etc. Apple gehört "NS" und Du machst Dein Eigenes.(...)

Das ist ein guter Hinweis, vielen Dank. Hier habe ich mich am Buch orientiert, aber das hindert mich ja nicht daran an Stellen wo es sinnvoll erscheint davon abzuweichen ;)

(...)
Gewöhne Dir nicht nicht diese Mischmasch-Schreibweise ohne Klammern beim if-else-an.(...)

Auch das werde ich ab sofort beherzigen!

(...)
Keine if-Bedingungen mit unzähliger UND-ODER-Verschachtelung.
Gewöhne Dir Return-Early an. Zumal der Code in den meisten Fällen performanter wird.(...)

Oha, um sicher zu gehen, dass ich das korrekt verstanden habe versuche ich das wieder in ein Beispiel zu verpacken:
statt:
Code:
-(BOOL) Method:(int) value
{
   
    BOOL variable = NO;
   
    if (self < value){
        variable = YES;}
    return variable;
}

lieber:

Code:
-(BOOL) Method:(int) value
{
   if (self < value)
    {
        return YES};
   else
    {
        return NO};
}

Meinst Du das mit "Return-Early"?

(...)
Prüfe Parameter gegen nil bzw. wenn zu erwarten NULL!(...)
[array addObject:eek:bject] … das kracht.(...)

Ja, absolut korrekt. Das habe ich eigentlich im Buch auch so gelernt und umgesetzt. Hier im "Minimalbeispiel" aber nicht ... Aber soweit, dass ich Dein Beispiel verstehe bin ich leider noch nicht ...

Und das Wichtigste vergessen :D(...)

Oha, jetzt bekomm ichs aber faustdick ;)

(...)
Es wird großen Wert auf selbsterklärende Methoden-, Parameternamen etc. gelegt.
Der Quelltext sollte "sprechend" sein.(...)

Guter Hinweis.

little_pixel, Vielen Dank für Deine Ratschläge und die Zeit die Du Dir dafür genommen hast.

Viele Grüße

André
 
Meinst Du das mit "Return-Early"?
Jein :D
Als solches hast Du verstanden was ich meine, aber in Deinem Beispiel ist ein super "Fehler" für die Zukunft versteckt.
Du machst nur einen return innerhalb des if-else-Konstrukts. Das ist jetzt absolut korrekt und funktioniert immer.
Aber in dem if- bzw. else-Bereich hast Du zukünftig Code, komplex oder lang stehen.
Das führt dazu, dass innerhalb Deines if-else vielleicht das return nicht erreicht wird. Konkret heißt das, dass am Ende der Methode ein return fehlt.

Bei mir sieht so etwas so aus:

Code:
-(BOOL)calcualteWithDivisor:(double)divisor
{
   
    // …
   
    if(divisor <= 0.0) // we don't do a division by zero
    {
   
        return NO;
   
    }
   
    // …
   
    // do our calculation
   
    // …
   
    return YES;
   
    // …
   
}

Das "Lustige" ist, dass Du mit return-early absolut selten eine Else benötigst ;-)
Oder anders gesagt, sogar weniger Coder schreibst bei höherer Qualität.

Viele Grüße
 
Hallo little_pixel,

(...)dass innerhalb Deines if-else vielleicht das return nicht erreicht wird. Konkret heißt das, dass am Ende der Methode ein return fehlt.(...) Das "Lustige" ist, dass Du mit return-early absolut selten eine Else benötigst(...)

Danke, ich "glaube/vermute" dass ich es verstanden habe. Nette Ratschläge und Tipps!

Viele Grüße

André
 
Zurück
Oben Unten