Getter und Setter sind Methoden, mit denen du den Wert einer Eigenschaft eines Objekts lesen und schreiben kannst. Crystal hat Makros, mit denen sich Getter und Setter für eine Eigenschaft einfach definieren lassen. Makros sind eine Möglichkeit, Code zur Kompilierzeit zu erzeugen, worauf wir später im Makro-Konzept eingehen.
In Ruby werden diese Methoden mit den Methoden attr_reader, attr_writer und attr_accessor definiert und ähneln oberflächlich betrachtet der Umsetzung in Crystal.
In Crystal sind sie als die Makros getter, setter und property definiert.
Ein Getter ist ein Makro, das eine Methode definiert, die den Wert einer Instanzvariable zurückgibt.
Das bedeutet, dass du kein @ mehr vor die Instanzvariable schreiben musst, wenn du auf sie zugreifen willst (in Methoden, außer in initialize). Stattdessen kannst du die Methode aufrufen, die das Getter-Makro definiert hat.
Das Getter-Makro kann mehrere Instanzvariablen annehmen, wenn du sie mit Kommas trennst.
# This:
class Person
@name : String
@age : Int32
def name
@name
end
def age
@age
end
end
# Is the same as this:
class Person
@name : String
@age : Int32
getter name, :age
end
Wie du siehst, reduziert die Verwendung von Gettern die Menge an Code, die du schreibst, und macht ihn leichter lesbar. Außerdem unterscheiden sich Ruby und Crystal darin, dass Crystal sowohl den Variablennamen als auch das Symbol als Argument für das Getter-Makro akzeptiert. Symbole werden später im Symbol-Konzept behandelt.
Ein Setter ist ein Makro, das eine Methode definiert, die den Wert einer Instanzvariable setzt.
Dieses Makro ist nicht besonders häufig anzutreffen; stattdessen wird meistens das property-Makro verwendet.
Die Methoden, die erzeugt werden, sehen wie name_of_method= aus; das = sorgt dafür, dass die Eigenschaft gesetzt werden kann.
Diese Methodendefinition ist etwas Besonderes, da das Argument, das die Methode erhält, hinter dem =-Zeichen steht.
Einige andere spezielle Methoden in Crystal verwenden diese Syntax, zum Beispiel die +-Methode.
Wie beim Getter-Makro kannst du, wenn du den Wert einer Instanzvariable nach dem Definieren eines Setters aktualisieren willst, die Methode aufrufen, die das Setter-Makro definiert hat.
# This:
class Person
@name : String
@age : Int32
def name=(name : String)
@name = name
end
def age=(age : Int32)
@age = age
end
end
# Is the same as this:
class Person
@name : String
@age : Int32
setter name, :age
end
Das property-Makro definiert sowohl einen Getter als auch einen Setter für eine Instanzvariable.
class Person
@name : String
@age : Int32
property name, :age
end
In dieser Übung modellierst du eine Waage.
Beim Initialisieren sollte sich die Waage an ihren Werkseinstellungen orientieren, die davon abhängen, wo die Waage verkauft wird. Dabei soll die Waage mit einer Genauigkeit initialisiert werden können und damit, ob sie metrisch oder imperial ist.
Implementiere die Methode WeighingMachine#initialize, die zwei Argumente entgegennimmt: precision, eine Int32, und metric, ein Bool.
Das Argument metric bedeutet, wenn es true ist, dass die Waage das metrische System verwenden soll, andernfalls soll sie das imperiale System verwenden.
Die initialize-Methode soll außerdem die Instanzvariable @weight auf 0.0 setzen.
precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
Um unterschiedliche Anforderungen zu erfüllen, kann jede Waage mit einer Genauigkeit angepasst werden (die Anzahl der Stellen nach dem Dezimaltrennzeichen).
Implementiere die Getter-Methode WeighingMachine#precision, die die Genauigkeit der Waage zurückgibt.
precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
vm.precision
# => 3
Implementiere die Eigenschaft WeighingMachine#weight, mit der das Gewicht gelesen und gesetzt werden kann:
precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
wm.weight = 60.5
wm.weight
# => 60.5
wm.weigh
# => 60.5
Implementiere die Eigenschaft WeighingMachine#metric=, mit der die Einheit gesetzt werden kann.
Sie soll einen booleschen Wert akzeptieren.
precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
vm.weight = 60.5
wm.metric = false
vm.weigh
# => 133.377
Melde dich bei Exercism an, um Crystal mit 26 Konzepte142 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.