الـgetter والـsetter طريقتان تتيحان لك قراءة قيمة خاصية كائن وكتابتها.
تمتلك Crystal ماكروات، وهذا يسهّل تعريف getter وsetter لخاصية ما.
الماكروات وسيلة لتوليد الكود في وقت الترجمة، وسنغطيها لاحقًا في مفهوم الماكرو.
في Ruby تُعرَّف هذه الطرق باستخدام الطرق attr_reader وattr_writer وattr_accessor، وهي تشبه من حيث المظهر تطبيق Crystal لها إلى حد كبير.
وقد عرّفت Crystal هذه في صورة ماكروات getter وsetter وproperty.
getter
getter ماكرو يعرّف طريقة تُرجع قيمة متغير نسخة.
وهذا يعني أنك لم تعد مضطرًا لكتابة @ أمام متغير النسخة عندما تريد الوصول إليه (داخل الطرق، باستثناء initialize)؛ وبدلًا من ذلك يمكنك استدعاء الطريقة التي عرّفها ماكرو getter.
يمكن لماكرو getter أن يقبل عدة متغيرات نسخة تفصل بينها فواصل.
# 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
كما ترى، يقلّل استخدام getter من كمية الكود الذي تكتبه، ويجعل قراءته أسهل.
وتختلف Crystal عن Ruby أيضًا في أنها تقبل اسم المتغير والرمز معًا كوسائط لماكرو getter.
وسنغطي الرموز لاحقًا في مفهوم الرموز.
setter
setter ماكرو يعرّف طريقة تضبط قيمة متغير نسخة.
لا يُصادف هذا الماكرو كثيرًا، وعادةً يُستخدم ماكرو property بدلًا منه.
ستبدو الطرق التي ستُنشَأ على هيئة name_of_method=؛ فعلامة = هي ما يتيح ضبط الخاصية.
تعريف هذه الطريقة خاص بعض الشيء، لأن الوسيط الذي تستقبله الطريقة يأتي بعد علامة =.
وتستخدم طرق أخرى خاصة عديدة في Crystal هذا التركيب، مثل طريقة +.
وكما في ماكرو getter، عندما تريد تحديث قيمة متغير نسخة بعد تعريف setter، يمكنك استدعاء الطريقة التي عرّفها ماكرو setter.
# 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
propertyproperty ماكرو يعرّف كلاً من getter وsetter لمتغير نسخة.
class Person
@name : String
@age : Int32
property name, :age
end
في هذا التمرين ستقوم بنمذجة آلة وزن.
عند تهيئتها، ينبغي أن تعتمد آلة الوزن على إعدادات المصنع، وهي تختلف باختلاف المكان الذي تُباع فيه الآلة. ولذلك ينبغي أن يكون بالإمكان تهيئة الآلة بدقة معيّنة، وبما يحدد ما إذا كانت تستخدم النظام المتري أم الإمبراطوري.
نفّذ الطريقة WeighingMachine#initialize التي تأخذ وسيطين: precision وهو Int32، وmetric وهو Bool.
الوسيط metric عندما يكون true يعني أن الآلة ينبغي أن تستخدم النظام المتري، وإلا فينبغي أن تستخدم النظام الإمبراطوري.
كما ينبغي أن تعيّن طريقة التهيئة أيضًا متغير المثيل @weight إلى 0.0.
precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
لتلبية الاحتياجات المختلفة، نسمح بتخصيص كل آلة وزن بدقة معيّنة (عدد الأرقام بعد الفاصلة العشرية).
نفّذ طريقة الجلب WeighingMachine#precision لتُرجع دقة آلة الوزن.
precision = 3
metric = true
vm = WeighingMachine.new(precision, metric)
vm.precision
# => 3
نفّذ الخاصية WeighingMachine#weight للسماح بجلب الوزن _و_تعيينه:
precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
wm.weight = 60.5
wm.weight
# => 60.5
wm.weigh
# => 60.5
نفّذ الخاصية WeighingMachine#metric= للسماح بتعيين الوحدة.
ينبغي أن تقبل قيمة منطقية.
precision = 3
metric = true
wm = WeighingMachine.new(precision, metric)
vm.weight = 60.5
wm.metric = false
vm.weigh
# => 133.377
سجّل في Exercism لتتعلّم وتتقن Crystal عبر 26 مفهومًا142 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.