গেটার ও সেটার হলো এমন মেথড, যা দিয়ে আপনি একটি অবজেক্টের প্রপার্টির মান পড়তে ও লিখতে পারেন। Crystal-এ ম্যাক্রো আছে, যার ফলে একটি প্রপার্টির জন্য গেটার ও সেটার ডিফাইন করা সহজ হয়ে যায়। ম্যাক্রো হলো কম্পাইল টাইমে কোড জেনারেট করার একটি উপায়, যা ম্যাক্রো কনসেপ্টে পরে আলোচনা করা হবে।
Ruby-তে এই মেথডগুলো attr_reader, attr_writer এবং attr_accessor মেথড দিয়ে ডিফাইন করা হয় এবং বাইরে থেকে দেখতে Crystal-এর বাস্তবায়নের সাথে খুবই মিল।
Crystal এগুলোকে getter, setter এবং property ম্যাক্রো হিসেবে ডিফাইন করেছে।
গেটার হলো একটি ম্যাক্রো, যা একটি ইনস্ট্যান্স ভ্যারিয়েবলের মান রিটার্ন করে এমন একটি মেথড ডিফাইন করে।
এর মানে হলো, অ্যাক্সেস করতে চাইলে আর ইনস্ট্যান্স ভ্যারিয়েবলের সামনে @ লিখতে হয় না (initialize বাদে মেথডের ভেতরে); বদলে আপনি গেটার ম্যাক্রো যে মেথডটি ডিফাইন করেছে সেটি কল করতে পারেন।
গেটার ম্যাক্রো কমা দিয়ে আলাদা করে একাধিক ইনস্ট্যান্স ভ্যারিয়েবল নিতে পারে।
# 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
আপনি দেখতেই পাচ্ছেন, গেটার ব্যবহার করলে আপনার লেখা কোডের পরিমাণ কমে যায় এবং কোড পড়তে সহজ হয়। এছাড়াও Ruby আর Crystal-এর মধ্যে একটি পার্থক্য আছে: Crystal গেটার ম্যাক্রোর আর্গুমেন্ট হিসেবে ভ্যারিয়েবলের নাম ও সিম্বল, দুটোই গ্রহণ করে। সিম্বল নিয়ে সিম্বল কনসেপ্টে পরে আলোচনা করা হবে।
সেটার হলো একটি ম্যাক্রো, যা একটি ইনস্ট্যান্স ভ্যারিয়েবলের মান সেট করে এমন একটি মেথড ডিফাইন করে।
এই ম্যাক্রো খুব একটা দেখা যায় না, সাধারণত এর বদলে property ম্যাক্রো ব্যবহার করা হয়।
যে মেথডগুলো তৈরি হবে সেগুলো দেখতে name_of_method= এর মতো হবে; এই = চিহ্নটিই প্রপার্টি সেট করা সম্ভব করে তোলে।
এই মেথড ডেফিনিশনটি একটু বিশেষ, কারণ মেথড যে আর্গুমেন্টটি পায় সেটি = চিহ্নের পরে থাকে।
Crystal-এ আরও কিছু বিশেষ মেথড এই সিনট্যাক্স ব্যবহার করে, যেমন + মেথড।
গেটার ম্যাক্রোর মতোই, সেটার ডিফাইন করার পরে ইনস্ট্যান্স ভ্যারিয়েবলের মান আপডেট করতে চাইলে আপনি সেটার ম্যাক্রো যে মেথডটি ডিফাইন করেছে সেটি কল করতে পারেন।
# 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
প্রপার্টি হলো একটি ম্যাক্রো, যা একটি ইনস্ট্যান্স ভ্যারিয়েবলের জন্য গেটার ও সেটার দুটোই ডিফাইন করে।
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টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।