2014-01-05 16 views
5

Ich versuche, eine unveränderliche POINT Klasse in Eiffel zu machen. Definiert der folgende Code einen? Die {NONE} Erreichbarkeit für die x und y Felder ist genug dafür? Kann ich etwas in die Klasseninvariante wie x = x' schreiben, oder wie kann ich sonst Unveränderlichkeit erreichen?Unveränderbare Klasse in Eiffel

class POINT 
    create 
     make 
    feature {NONE} 
     x: DOUBLE 
     y: DOUBLE 
    feature 
     make (x_: DOUBLE; y_: DOUBLE) 
     do 
      x := x_ 
      y := y_ 
     ensure 
      set: x = x_ and y = y_ 
     end 

    feature --accessors 
     get_x: DOUBLE 
     do 
      Result := x 
     ensure 
      Result = x 
     end 
    end 
+2

note Nach dem Eiffel-Stil Leitfaden Accessoren sind Substantive, daher keine get-Präfix. Dadurch wird Ihr Code leichter lesbar (dies gilt für fast alle Sprachen). Aber auch wenn Sie dem Attribut einen eigenen Accessor geben, siehe Antwort unten, wird es kein get-Präfix haben. –

Antwort

5

Eiffel erlaubt nicht, Attribute einer Klasse durch seine Kunden zu ändern. Beispielsweise wird der folgende Code abgelehnt:

p: POINT 
... 
p.x := 5.0 

Als Ergebnis gibt es keine Notwendigkeit Getter, um (wie in einigen anderen Sprachen). Sie können einfach p.x verwenden, vorausgesetzt, dass x ausreichend in eine Client-Klasse exportiert wird. So kann der Code von Ihrem Beispiel zu

class POINT 
create 
    make 
feature -- Access 
    x: DOUBLE 
    y: DOUBLE 
feature {NONE} -- Creation 
    make (x0: DOUBLE; y0: DOUBLE) 
     -- Initialize object with `x0' and `y0'. 
    do 
     x := x0 
     y := y0 
    ensure 
     set: x = x0 and y = y0 
    end 
end 

Hinweis vereinfacht werden, dass die Schaffung Verfahren ist nicht mehr exportierte, sonst wäre es möglich, es zu benutzen als ein normales (dh nicht-creation) Routine und ändern Sie die Attribute, ist, dass wir in der Lage, etwas zu tun wie folgt

create p.make (1, 1) 
p.make (2, 3) 
print (p) 

und dies würde (2, 3) drucken, dh der Wert des ursprünglichen Objekts p zu ändern wäre in der Lage, es wandelbar machen.

Obwohl die Attribute jetzt nicht direkt geändert werden können, ist es immer noch möglich, die Funktion copy für ein Objekt vom Typ POINT aufzurufen und das gesamte Objekt zu ändern. Wenn Sie diese Situation als auch vermeiden will, kann die Funktion in der Klasse neu definiert wird POINT eine Ausnahme zu erhöhen, oder sogar eine Nachbedingung False wodurch die Laufzeit zu haben, eine Ausnahme für Sie zu erhöhen:

copy (other: like Current) 
     -- <Precursor> 
    do 
     (create {EXCEPTIONS}).raise ("Attempt to change an immutable object.") 
    ensure then 
     is_allowed: False 
    end 
+1

Wenn Sie "p.x: = 5.0" verwenden möchten, beachten Sie, dass Sie einen Assigner verwenden können. Siehe: http://docs.eiffel.com/book/examples/example-self-initializing-attributes-and-assigner-commands. –

+0

Ich verstehe es nicht, was passiert, wenn ich die Marke auf privat setzen? jetzt, wenn ich rufe: create p1.make (1, 1); Druck (p1); \t erstellen p1.make (2, 3); drucken (p1) als ich bekomme ein Ergebnis: (1, 1) (2, 3) und das gleiche passiert, wenn die Sichtbarkeit nicht gesetzt ist –

+0

und wenn ich von dieser Klasse erben, Ich kann das make-Feature immer noch neu definieren, aber {NONE} gibt an, dass selbst die untergeordneten Klassen das Feature nicht ändern können. oder die create-Methode hat verschiedene Regeln? –

Verwandte Themen