লুয়া (Lua) প্রোগ্রামিং ভাষায় মেটাটেবিল (Metatables) এবং মেটামেথড (Metamethods) একটি অত্যন্ত শক্তিশালী এবং উন্নত কনসেপ্ট, যা টেবিলের আচরণ কাস্টমাইজ করতে সহায়তা করে। আপনি মেটাটেবিল ব্যবহার করে একটি টেবিলের মধ্যে কোনো নির্দিষ্ট কার্যকারিতা, অপারেশন, বা আচরণ যোগ করতে পারেন। এই আচরণগুলোকে মেটামেথড বলা হয় এবং এটি আপনার কোডের কার্যক্ষমতা এবং নমনীয়তা বাড়াতে সাহায্য করে।
১. মেটাটেবিল (Metatables)
মেটাটেবিল হচ্ছে এমন একটি টেবিল যা অন্য টেবিলের আচরণ কাস্টমাইজ করার জন্য ব্যবহৃত হয়। একটি টেবিলের মেটাটেবিল সেট করা হলে, সেই টেবিলটি মেটাটেবিলের ডিফাইন করা কার্যকারিতা বা অপারেশন গ্রহণ করবে। এটি সাধারণত অপারেটর কাস্টমাইজেশন, ইনডেক্সিং এবং অবজেক্ট প্রোগ্রামিং এর জন্য ব্যবহৃত হয়।
মেটাটেবিল সেট করা (Setting a Metatable)
লুয়া ভাষায় টেবিলের মেটাটেবিল সেট করার জন্য setmetatable() ফাংশন ব্যবহার করা হয়।
সিনট্যাক্স:
setmetatable(table, metatable)এখানে table হলো মূল টেবিল এবং metatable হলো মেটাটেবিল।
উদাহরণ:
person = {name = "Alice", age = 30}
-- মেটাটেবিল তৈরি
meta = {
__index = function(table, key)
if key == "greet" then
return "Hello, " .. table.name
end
end
}
-- মেটাটেবিল সেট করা
setmetatable(person, meta)
print(person.greet) -- আউটপুট: Hello, Aliceএখানে, __index মেটামেথড ব্যবহার করা হয়েছে, যা greet কীগুলোর জন্য কাস্টম আউটপুট প্রদান করছে।
২. মেটামেথড (Metamethods)
মেটামেথড হলো বিশেষ ফাংশন বা অপারেটর যা মেটাটেবিলে ডিফাইন করা হয় এবং টেবিলের আচরণ কাস্টমাইজ করতে ব্যবহৃত হয়। লুয়া মেটাটেবিলের মধ্যে কিছু বিশেষ ধরনের মেটামেথড রয়েছে, যা বিভিন্ন ধরনের কার্যক্রম বা অপারেশন কাস্টমাইজ করতে সহায়তা করে। এই মেটামেথডগুলোর মাধ্যমে আমরা টেবিলের স্বাভাবিক আচরণ পরিবর্তন করতে পারি।
সাধারণ মেটামেথডস:
__index: এটি ব্যবহার করা হয় যখন টেবিলের এমন কোনো কিয়া অ্যাক্সেস করা হয় যা বিদ্যমান নেই।__newindex: এটি ব্যবহার করা হয় যখন টেবিলের নতুন কোনো কিয়া সেট করা হয়।__add,__sub,__mul, etc.: বিভিন্ন অ্যারিথমেটিক অপারেশন কাস্টমাইজ করার জন্য।__call: এটি ব্যবহার করা হয় যখন টেবিল একটি ফাংশনের মতো কল করা হয়।
১. __index মেটামেথড
এই মেটামেথডটি টেবিলের মধ্যে যদি কোনো কিয়া না থাকে, তবে এটি অন্য একটি টেবিল থেকে মান নিয়ে আসতে সাহায্য করে।
উদাহরণ:
person = {name = "Alice", age = 30}
default = {name = "Unknown", age = 0}
-- মেটাটেবিল তৈরি
meta = {
__index = default -- যদি person টেবিলের কিয়া না থাকে, তাহলে default টেবিল থেকে মান নিবে
}
-- মেটাটেবিল সেট করা
setmetatable(person, meta)
print(person.name) -- আউটপুট: Alice (person এর মধ্যে name কিয়া আছে)
print(person.age) -- আউটপুট: 30 (person এর মধ্যে age কিয়া আছে)
print(person.address) -- আউটপুট: Unknown (person এর মধ্যে address কিয়া নেই, তাই default থেকে আসবে)এখানে, person টেবিলের মধ্যে যদি কোনো কিয়া না থাকে, তবে এটি default টেবিল থেকে মান নিবে।
২. __newindex মেটামেথড
এই মেটামেথডটি ব্যবহৃত হয় যখন একটি নতুন কিয়া একটি টেবিলের মধ্যে সেট করা হয়। এটি সাধারণত একটি কাস্টম আচরণ কনফিগার করতে ব্যবহৃত হয়।
উদাহরণ:
person = {name = "Alice", age = 30}
-- মেটাটেবিল তৈরি
meta = {
__newindex = function(table, key, value)
if key == "age" then
rawset(table, key, value) -- শুধুমাত্র age কিয়া আপডেট করবে
else
print("Cannot modify other properties")
end
end
}
-- মেটাটেবিল সেট করা
setmetatable(person, meta)
person.age = 35 -- age আপডেট হবে
print(person.age) -- আউটপুট: 35
person.name = "Bob" -- অন্য প্রপার্টি আপডেট করার চেষ্টা করলে
-- আউটপুট: Cannot modify other propertiesএখানে, person টেবিলের age কিয়া শুধুমাত্র আপডেট হতে পারে, এবং অন্য কিয়াগুলো আপডেট করা যাবে না।
৩. অপারেটর কাস্টমাইজেশন (Operator Overloading)
লুয়া ভাষায় আপনি +, -, *, / ইত্যাদি অপারেটরগুলোর আচরণ কাস্টমাইজ করতে পারেন। এটি মেটামেথড এর মাধ্যমে করা হয়।
উদাহরণ:
point1 = {x = 1, y = 2}
point2 = {x = 3, y = 4}
-- মেটাটেবিল তৈরি
meta = {
__add = function(p1, p2)
return {x = p1.x + p2.x, y = p1.y + p2.y}
end
}
-- মেটাটেবিল সেট করা
setmetatable(point1, meta)
setmetatable(point2, meta)
-- দুটি পয়েন্ট যোগ করা
result = point1 + point2
print(result.x, result.y) -- আউটপুট: 4 6এখানে, দুটি পয়েন্ট (point1 এবং point2) এর যোগফল কাস্টম মেটামেথডের মাধ্যমে নির্ধারণ করা হয়েছে।
৪. __call মেটামেথড
এই মেটামেথডটি ব্যবহৃত হয় যখন টেবিলকে একটি ফাংশন হিসেবে কল করা হয়।
উদাহরণ:
person = {name = "Alice"}
-- মেটাটেবিল তৈরি
meta = {
__call = function(table)
return "Hello, " .. table.name
end
}
-- মেটাটেবিল সেট করা
setmetatable(person, meta)
-- টেবিলকে ফাংশন হিসেবে কল করা
print(person()) -- আউটপুট: Hello, Aliceএখানে, person টেবিলকে একটি ফাংশন হিসেবে কল করা হয়েছে এবং এটি একটি কাস্টম গ্রীটিং রিটার্ন করছে।
সারসংক্ষেপ
লুয়া ভাষায় মেটাটেবিল এবং মেটামেথড অত্যন্ত শক্তিশালী কনসেপ্ট, যা টেবিলের আচরণ কাস্টমাইজ করতে সহায়তা করে। আপনি __index, __newindex, __add, __call ইত্যাদি মেটামেথড ব্যবহার করে টেবিলের আচরণ পরিবর্তন করতে পারেন এবং কোডকে আরও নমনীয় এবং শক্তিশালী করতে পারেন।
মেটাটেবিল (Metatables) হল একটি বিশেষ ধরনের টেবিল যা লুয়া ভাষায় টেবিলের আচরণ পরিবর্তন করতে ব্যবহৃত হয়। এটি লুয়া ভাষায় অবজেক্ট ও ক্লাসের ধারণার মতো কাজ করে এবং টেবিলগুলোর মধ্যে কাস্টম আচরণ নির্ধারণ করতে ব্যবহৃত হয়, যেমন: যোগ, বিয়োগ, সমতুল্যতা চেকিং, ইত্যাদি।
লুয়া ভাষায় মেটাটেবিলের মাধ্যমে টেবিলগুলির আচরণ কাস্টমাইজ করা যায় এবং এটি কোডের শক্তি এবং নমনীয়তা বাড়াতে সাহায্য করে।
মেটাটেবিল (Metatable) এর ধারণা
লুয়া ভাষায়, প্রতিটি টেবিলের সাথে একটি মেটাটেবিল সংযুক্ত করা যেতে পারে, যা তার আচরণ পরিবর্তন করে। মেটাটেবিলের মধ্যে কিছু বিশেষ ক্ষেত্র (fields) থাকে যা টেবিলের অপারেশনগুলোকে কাস্টমাইজ করে, যেমন:
__index: টেবিলের কোনো কী এক্সেস করার সময় যদি সেই কী টেবিলে না থাকে, তখন এই ফাংশনটি কল হয়।__newindex: টেবিলের কোনো নতুন কী-মান অ্যাসাইন করার সময় এই ফাংশনটি কল হয়।__add,__sub,__mul, etc.: গাণিতিক অপারেশনগুলোর জন্য কাস্টম আচরণ তৈরি করা যায় (যেমন, যোগ, বিয়োগ, গুণ ইত্যাদি)।__metatable: মেটাটেবিল অ্যাক্সেস করার জন্য একটি সীমাবদ্ধতা তৈরি করা যায়।
মেটাটেবিল মূলত কোডের মধ্যে টেবিলগুলোর আচরণ পরিবর্তন এবং কাস্টম অপারেশন বাস্তবায়ন করতে ব্যবহৃত হয়।
মেটাটেবিলের ব্যবহার
১. মেটাটেবিল সেট করা
মেটাটেবিল একটি টেবিলের সাথে যুক্ত করতে setmetatable ফাংশন ব্যবহার করা হয়। এর মাধ্যমে একটি টেবিলের আচরণ পরিবর্তন করা হয়।
উদাহরণ:
-- একটি টেবিল তৈরি করা
local myTable = {10, 20, 30}
-- একটি মেটাটেবিল তৈরি করা
local metaTable = {
__index = function(table, key)
return "Key not found: " .. key
end
}
-- টেবিলের সাথে মেটাটেবিল সেট করা
setmetatable(myTable, metaTable)
-- টেবিলের একটি অজানা কী অ্যাক্সেস করা
print(myTable[1]) -- আউটপুট: 10 (যেহেতু এটি টেবিলের একটি আসল মান)
print(myTable[5]) -- আউটপুট: Key not found: 5 (মেটাটেবিলের __index ফাংশন কল হবে)এখানে, myTable নামক একটি টেবিলের সাথে একটি মেটাটেবিল metaTable সংযুক্ত করা হয়েছে, এবং যখন myTable[5] কল করা হয়েছে, তখন মেটাটেবিলের __index ফাংশন চালু হয়েছে।
২. গাণিতিক অপারেশনের জন্য মেটাটেবিল
লুয়া মেটাটেবিলের মাধ্যমে আপনি গাণিতিক অপারেশনগুলোর আচরণ কাস্টমাইজ করতে পারেন, যেমন যোগ, বিয়োগ, গুণ ইত্যাদি।
উদাহরণ:
-- একটি টেবিল তৈরি করা
local vector1 = {x = 1, y = 2}
local vector2 = {x = 3, y = 4}
-- একটি মেটাটেবিল তৈরি করা
local metaTable = {
__add = function(v1, v2)
return {x = v1.x + v2.x, y = v1.y + v2.y}
end
}
-- টেবিলের সাথে মেটাটেবিল সেট করা
setmetatable(vector1, metaTable)
setmetatable(vector2, metaTable)
-- দুইটি টেবিল যোগ করা
result = vector1 + vector2
print(result.x, result.y) -- আউটপুট: 4 6এখানে, vector1 এবং vector2 দুটি টেবিলের সাথে মেটাটেবিল ব্যবহার করে তাদের যোগফল কাস্টমাইজ করা হয়েছে। __add ফাংশনের মাধ্যমে এই যোগফল কাস্টম আচরণ সৃষ্টি করা হয়েছে।
৩. __newindex ফাংশন ব্যবহার
__newindex ফাংশনটি তখন কল হয় যখন একটি নতুন কী এবং মান অ্যাসাইন করা হয় একটি টেবিলের মধ্যে। এটি সাধারণত নতুন মানের অ্যাসাইনমেন্টের আচরণ কাস্টমাইজ করতে ব্যবহৃত হয়।
উদাহরণ:
-- একটি টেবিল তৈরি করা
local myTable = {}
-- একটি মেটাটেবিল তৈরি করা
local metaTable = {
__newindex = function(table, key, value)
print("Attempting to set " .. key .. " to " .. value)
rawset(table, key, value) -- আসল টেবিলের মান সেট করা
end
}
-- টেবিলের সাথে মেটাটেবিল সেট করা
setmetatable(myTable, metaTable)
-- একটি নতুন কী-মান অ্যাসাইন করা
myTable.name = "Alice" -- আউটপুট: Attempting to set name to Aliceএখানে, যখন myTable.name সেট করা হয়েছে, তখন __newindex ফাংশন কল হয়েছে এবং নতুন কী-মান অ্যাসাইনমেন্টের আচরণ কাস্টমাইজ করা হয়েছে।
৪. __metatable ফাংশন ব্যবহার
__metatable ফাংশনটি মেটাটেবিলের অ্যাক্সেস নিয়ন্ত্রণ করতে ব্যবহৃত হয়। এটি একটি সীমাবদ্ধতা যোগ করে, যাতে মেটাটেবিল অ্যাক্সেস করা না যায়।
উদাহরণ:
-- একটি টেবিল তৈরি করা
local myTable = {}
-- একটি মেটাটেবিল তৈরি করা
local metaTable = {
__metatable = "Access Denied"
}
-- টেবিলের সাথে মেটাটেবিল সেট করা
setmetatable(myTable, metaTable)
-- মেটাটেবিল অ্যাক্সেসের চেষ্টা
print(getmetatable(myTable)) -- আউটপুট: Access Deniedএখানে, myTable এর মেটাটেবিল অ্যাক্সেস করা হলে "Access Denied" মেসেজ পাওয়া যাবে, কারণ __metatable এর মাধ্যমে এটি সীমাবদ্ধ করা হয়েছে।
সারসংক্ষেপ
লুয়া ভাষায় মেটাটেবিল (Metatables) ব্যবহার করে টেবিলগুলির আচরণ কাস্টমাইজ করা যায়, যেমন গাণিতিক অপারেশন, ইনডেক্সিং, নতুন মান অ্যাসাইনমেন্ট ইত্যাদি। মেটাটেবিল মূলত টেবিলের জন্য বিশেষ ফাংশন সংজ্ঞা দেয় এবং টেবিলের আচরণ পরিবর্তন করতে সাহায্য করে। এর মাধ্যমে আপনি কোডে কাস্টম আচরণ তৈরি করতে পারেন, যেমন:
__index: কী এক্সেস করার কাস্টম আচরণ।__newindex: নতুন কী-মান অ্যাসাইনমেন্টের কাস্টম আচরণ।__add,__sub,__mulইত্যাদি: গাণিতিক অপারেশনগুলির কাস্টম আচরণ।__metatable: মেটাটেবিল অ্যাক্সেস নিয়ন্ত্রণ।
মেটাটেবিলের মাধ্যমে টেবিলগুলির আচরণ আরও শক্তিশালী এবং নমনীয় করা যায়, যা কোডের পুনঃব্যবহারযোগ্যতা এবং কার্যক্ষমতা বাড়াতে সাহায্য করে।
লুয়া (Lua) ভাষায় মেটামেথডস (Metamethods) হল বিশেষ ফাংশন যা টেবিল (tables) বা অন্যান্য ডেটা স্ট্রাকচারকে কাস্টমাইজড আচরণ প্রদান করতে ব্যবহৃত হয়। মেটামেথডগুলোর মাধ্যমে আপনি কিভাবে টেবিলের সদস্য অ্যাক্সেস বা পরিবর্তন হবে, কিভাবে একটি অবজেক্টকে কল করা যাবে, এবং অন্যান্য আচার-আচরণ নিয়ন্ত্রণ করতে পারেন। মেটামেথড গুলি সাধারণত একটি মেটাটেবিল (metatable) এর মধ্যে সংরক্ষিত থাকে, এবং সেই মেটাটেবিলকে টেবিলের সাথে অ্যাসোসিয়েট করা হয়।
এই টিউটোরিয়ালে আমরা কিছু সাধারণ মেটামেথড যেমন __index, __newindex, __call, __add ইত্যাদির ব্যবহার এবং উদাহরণ দেখব।
১. __index মেটামেথড
__index মেটামেথডটি ব্যবহৃত হয় যখন আপনি একটি টেবিলের এমন কোন সদস্য অ্যাক্সেস করেন যা সেখানে উপস্থিত নেই। এটি একটি টেবিলের সদস্যের জন্য একটি ডিফল্ট মান বা কাস্টম আচরণ প্রদান করে।
উদাহরণ:
person = {name = "John", age = 30}
-- মেটাটেবিল তৈরি
mt = {
__index = function(table, key)
if key == "city" then
return "New York" -- ডিফল্ট মান প্রদান
else
return nil -- অন্য কোনো কিপর্যায়ে nil ফেরত
end
end
}
-- person টেবিলের সাথে মেটাটেবিল অ্যাসোসিয়েট করা
setmetatable(person, mt)
print(person.name) -- আউটপুট: John
print(person.city) -- আউটপুট: New York
print(person.country) -- আউটপুট: nilএখানে, person টেবিলের মধ্যে city কীগুলি নেই, তবে __index মেটামেথডের মাধ্যমে কাস্টম মান "New York" রিটার্ন করা হয়েছে।
২. __newindex মেটামেথড
__newindex মেটামেথডটি ব্যবহৃত হয় যখন আপনি একটি টেবিলের নতুন সদস্য সেট (assign) করার চেষ্টা করেন। এটি একটি কাস্টম আচরণ প্রদান করে, যেমন একটি নির্দিষ্ট কিপর্যায়ে একটি ভ্যালু প্রিভেন্ট (প্রতিরোধ) করা।
উদাহরণ:
person = {name = "John", age = 30}
-- মেটাটেবিল তৈরি
mt = {
__newindex = function(table, key, value)
if key == "age" and value < 18 then
print("Age must be at least 18.")
else
rawset(table, key, value) -- স্বাভাবিকভাবে মান সেট করা
end
end
}
setmetatable(person, mt)
person.age = 17 -- আউটপুট: Age must be at least 18.
person.age = 25 -- এটা সফলভাবে age কে 25 সেট করবে
print(person.age) -- আউটপুট: 25এখানে, age এর জন্য __newindex ব্যবহার করা হয়েছে যাতে যেকোনো বয়স ১৮ এর কম হলে সেট করা না যায়।
৩. __call মেটামেথড
__call মেটামেথডটি ব্যবহৃত হয় যখন আপনি একটি টেবিলকে একটি ফাংশনের মতো কল করতে চান। এটি টেবিলকে একটি ফাংশনে রূপান্তরিত করে এবং সেই টেবিলের মধ্যে কাস্টম আচরণ চালাতে সক্ষম হয়।
উদাহরণ:
person = {
name = "John",
age = 30,
__call = function(self)
print("Calling " .. self.name .. " who is " .. self.age .. " years old.")
end
}
setmetatable(person, person)
person() -- আউটপুট: Calling John who is 30 years old.এখানে, person টেবিলকে একটি ফাংশন হিসেবে কল করা হয়েছে এবং __call মেটামেথডের মাধ্যমে কাস্টম আচরণ সম্পাদিত হয়েছে।
৪. __add মেটামেথড
__add মেটামেথডটি ব্যবহৃত হয় যখন আপনি দুটি টেবিল বা সংখ্যা যোগ করার চেষ্টা করেন। এটি টেবিল বা অন্য ডেটা টাইপের মধ্যে কাস্টম যোগফল নির্ধারণ করতে ব্যবহৃত হয়।
উদাহরণ:
point1 = {x = 1, y = 2}
point2 = {x = 3, y = 4}
-- মেটাটেবিল তৈরি
mt = {
__add = function(p1, p2)
return {x = p1.x + p2.x, y = p1.y + p2.y}
end
}
setmetatable(point1, mt)
setmetatable(point2, mt)
-- দুইটি পয়েন্ট যোগ করা
result = point1 + point2
print(result.x) -- আউটপুট: 4
print(result.y) -- আউটপুট: 6এখানে, point1 এবং point2 এর মধ্যে __add মেটামেথড ব্যবহার করে দুটি পয়েন্টের যোগফল বের করা হয়েছে।
৫. অন্যান্য মেটামেথড
লুয়া ভাষায় আরও অনেক মেটামেথড রয়েছে, যেমন:
__tostring: এটি টেবিলের একটি কাস্টম স্ট্রিং রিপ্রেজেন্টেশন তৈরি করে।__mul: এটি টেবিলের জন্য কাস্টম গুণফল নির্ধারণ করতে ব্যবহৃত হয়।__sub: এটি টেবিলের জন্য কাস্টম বিয়োগফল নির্ধারণ করতে ব্যবহৃত হয়।__metatable: এটি টেবিলের মেটাটেবিল অ্যাক্সেসকে নিয়ন্ত্রণ করতে ব্যবহৃত হয়।
সারসংক্ষেপ
লুয়া ভাষায় মেটামেথড একটি শক্তিশালী ফিচার যা টেবিলের আচরণ কাস্টমাইজ করতে সহায়তা করে। আপনি __index, __newindex, __call, __add এবং অন্যান্য মেটামেথড ব্যবহার করে টেবিলের আচরণ নিয়ন্ত্রণ করতে পারেন এবং একটি টেবিলকে অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিং (OOP) স্টাইলে ব্যবহার করতে পারেন। মেটামেথড ব্যবহার করে আপনি টেবিলের উপর বিভিন্ন কাস্টম কার্যক্রম এবং অপারেশন নির্ধারণ করতে পারেন।
লুয়া ভাষায় অপারেটর ওভারলোডিং (Operator Overloading) এবং মেটামেথডস (Metamethods) ব্যবহার করে আপনি কাস্টম ডেটা টাইপের জন্য অপারেটর গুলি কাস্টমাইজ করতে পারেন। লুয়া ভাষায় মেটামেথডস হল বিশেষ ফাংশন যা টেবিলের জন্য নির্দিষ্ট অপারেশন পরিচালনা করতে ব্যবহৃত হয়। মেটামেথডসের মাধ্যমে আপনি অপারেটরের আচরণ নির্ধারণ করতে পারেন।
লুয়া ভাষায় অপারেটর ওভারলোডিং সরাসরি সমর্থিত না হলেও, মেটামেথডসের মাধ্যমে আপনি এটি সম্ভব করতে পারেন। এখানে, আমরা মেটামেথডস ব্যবহার করে অপারেটর ওভারলোডিংয়ের ধারণা এবং উদাহরণ দেখব।
১. মেটামেথডস (Metamethods) কী?
মেটামেথডস হল লুয়া টেবিলের জন্য নির্দিষ্ট ফাংশন যেগুলি একটি টেবিলের ওপর বিভিন্ন অপারেশন বাস্তবায়ন করে। এগুলি সাধারণত টেবিলের সাথে যুক্ত থাকে এবং কিছু বিশেষ শর্তে (যেমন, যোগফল, বিয়োগফল) অটোমেটিকভাবে কল হয়। মেটামেথডস কাস্টম ডেটা টাইপের জন্য অপারেটরের আচরণ কাস্টমাইজ করতে ব্যবহৃত হয়।
লুয়া ভাষায় কিছু জনপ্রিয় মেটামেথডস:
__add:+অপারেটর__sub:-অপারেটর__mul:*অপারেটর__div:/অপারেটর__mod:%অপারেটর__tostring: টেবিলকে স্ট্রিং এ রূপান্তর
২. অপারেটর ওভারলোডিং এর জন্য মেটামেথডস ব্যবহার
লুয়া টেবিলের জন্য কাস্টম অপারেটর তৈরি করতে, আমরা একটি টেবিলের মেটামেথডস ব্যবহার করি। এই মেটামেথডটি সেই টেবিলের ওপর অপারেশন চালানো হলে কল হবে।
উদাহরণ:
ধরা যাক, আমরা একটি কাস্টম টাইপ Vector তৈরি করব এবং এই Vector টাইপের জন্য + এবং - অপারেটর গুলি কাস্টমাইজ করব।
-- কাস্টম টেবিল 'Vector' তৈরি
Vector = {}
Vector.__index = Vector
-- Vector এর কনস্ট্রাকটর
function Vector.new(x, y)
local self = setmetatable({}, Vector)
self.x = x
self.y = y
return self
end
-- __add মেটামেথড ব্যবহার করে '+' অপারেটর কাস্টমাইজ করা
function Vector.__add(v1, v2)
return Vector.new(v1.x + v2.x, v1.y + v2.y)
end
-- __sub মেটামেথড ব্যবহার করে '-' অপারেটর কাস্টমাইজ করা
function Vector.__sub(v1, v2)
return Vector.new(v1.x - v2.x, v1.y - v2.y)
end
-- __tostring মেটামেথড ব্যবহার করে স্ট্রিং রূপান্তর
function Vector.__tostring(v)
return "(" .. v.x .. ", " .. v.y .. ")"
end
-- টেস্ট কোড
v1 = Vector.new(1, 2)
v2 = Vector.new(3, 4)
v3 = v1 + v2 -- __add মেটামেথড কল হবে
print(v3) -- আউটপুট: (4, 6)
v4 = v1 - v2 -- __sub মেটামেথড কল হবে
print(v4) -- আউটপুট: (-2, -2)এখানে:
Vector.__add:+অপারেটরের জন্য কাস্টম মেটামেথড, যা দুটিVectorঅবজেক্টের মান যোগ করে নতুন একটিVectorতৈরি করবে।Vector.__sub:-অপারেটরের জন্য কাস্টম মেটামেথড, যা দুটিVectorঅবজেক্টের মান বিয়োগ করে নতুন একটিVectorতৈরি করবে।Vector.__tostring: এই মেটামেথড স্ট্রিং রূপেVectorঅবজেক্টের মান প্রদর্শন করতে ব্যবহৃত হয়।
৩. অন্য মেটামেথডস এবং তাদের ব্যবহার
লুয়া ভাষায় অন্যান্য মেটামেথডস যেমন __mul, __div, __mod, এবং __eq (ইকুয়ালিটি চেক) ইত্যাদি রয়েছে, যেগুলিকে কাস্টম অপারেশনসের জন্য ব্যবহৃত হতে পারে।
উদাহরণ: __mul (গুণফল অপারেটর)
function Vector.__mul(v1, scalar)
return Vector.new(v1.x * scalar, v1.y * scalar)
end
v5 = v1 * 2 -- __mul মেটামেথড কল হবে
print(v5) -- আউটপুট: (2, 4)এখানে, __mul মেটামেথডটি ব্যবহার করে একটি Vector অবজেক্টকে একটি স্কেলার মানের (যেমন 2) সাথে গুণ করা হচ্ছে।
উদাহরণ: __eq (ইকুয়ালিটি অপারেটর)
function Vector.__eq(v1, v2)
return v1.x == v2.x and v1.y == v2.y
end
print(v1 == v2) -- আউটপুট: falseএখানে, __eq মেটামেথডটি ব্যবহার করে দুটি Vector অবজেক্টের সমতা পরীক্ষা করা হচ্ছে।
৪. মেটামেথডস এবং মেটাটেবিল (Metatables)
লুয়া ভাষায় মেটামেথডস একটি টেবিলের সাথে যুক্ত থাকে মেটাটেবিল (Metatable) এর মাধ্যমে। যখন একটি টেবিলের উপর কোনো অপারেশন করা হয়, মেটাটেবিলটি সেই অপারেশনটি পরিচালনা করবে।
local v1 = Vector.new(1, 2)
local v2 = Vector.new(3, 4)
-- মেটাটেবিল সেট করা
setmetatable(v1, Vector)
setmetatable(v2, Vector)
-- এইভাবে মেটাটেবিলের মাধ্যমে মেটামেথডস কল করা হয়।এখানে, setmetatable ফাংশনটি v1 এবং v2 টেবিলগুলিতে মেটাটেবিল সেট করে, যা মেটামেথডগুলি কার্যকর করতে সহায়তা করে।
সারসংক্ষেপ
- মেটামেথডস হল লুয়া টেবিলের জন্য বিশেষ ফাংশন যা অপারেটরের আচরণ কাস্টমাইজ করে।
- অপারেটর ওভারলোডিং: মেটামেথডস যেমন
__add,__sub,__mul,__divইত্যাদি ব্যবহার করে আপনি কাস্টম অপারেটর তৈরি করতে পারেন। - মেটাটেবিল: মেটামেথডস টেবিলের সাথে যুক্ত থাকে মেটাটেবিলের মাধ্যমে, এবং এটি টেবিলের উপর অপারেশন পরিচালনা করে।
এই কৌশলটি লুয়া ভাষায় কাস্টম ডেটা টাইপ তৈরি ও অপারেটর কাস্টমাইজ করতে সাহায্য করে, যা কোডের পুনঃব্যবহারযোগ্যতা এবং পরিষ্কারতা বাড়ায়।
লুয়া একটি প্রোটোটাইপাল ভাষা, যার মানে হল যে এটি ক্লাস এবং অবজেক্ট ভিত্তিক OOP (Object-Oriented Programming) সরাসরি সমর্থন করে না, তবে Metatables ব্যবহার করে আপনি লুয়া ভাষায় অবজেক্ট-ওরিয়েন্টেড ডিজাইন (OOP) তৈরি করতে পারেন। Metatables লুয়া ভাষার একটি শক্তিশালী বৈশিষ্ট্য, যা আপনি অবজেক্ট তৈরি, ইনহেরিটেন্স, পলিমরফিজম এবং অন্যান্য OOP কনসেপ্ট সিমুলেট করতে ব্যবহার করতে পারেন।
এখানে আমরা Metatables ব্যবহার করে লুয়া ভাষায় একটি Object-Oriented Design কিভাবে তৈরি করা যায় তা বিস্তারিতভাবে আলোচনা করব।
১. Metatables এবং OOP
লুয়া ভাষায় metatables টেবিলগুলোর উপর অতিরিক্ত আচরণ সংজ্ঞায়িত করতে ব্যবহৃত হয়। যখন আপনি একটি টেবিলকে একটি metatable অ্যাসাইন করেন, তখন সেটি কিছু বিশেষ ফাংশনের মাধ্যমে পরিবর্তিত হয়, যেমন:
__index: টেবিলের একটি নতুন কিপেয়ে মান চাওয়ার জন্য।__newindex: টেবিলের নতুন কিপেয়ে মান সেট করার জন্য।__call: টেবিলকে ফাংশন হিসেবে কল করার জন্য।__tostring: টেবিলকে স্ট্রিং হিসেবে রূপান্তর করার জন্য।
এগুলোর মাধ্যমে, আপনি একটি class-like structure তৈরি করতে পারেন এবং ক্লাসের ফাংশনগুলি methods হিসেবে ব্যবহার করতে পারেন।
২. Metatables দিয়ে Object-Oriented Design তৈরি করা
লুয়া ভাষায় OOP বাস্তবায়ন করতে metatables ব্যবহার করে টেবিলগুলিকে ক্লাসের মতো আচরণ করানো যায়। এখানে আমরা একটি সাধারণ উদাহরণ দেখাবো, যেখানে একটি Person ক্লাস তৈরি করা হয়েছে এবং methods সহ ইনস্ট্যান্স তৈরি করা হয়েছে।
২.১. ক্লাস তৈরি এবং ইনস্ট্যান্স তৈরি করা
-- Person ক্লাস তৈরি
Person = {}
Person.__index = Person
-- Person এর constructor (new)
function Person.new(name, age)
local self = setmetatable({}, Person)
self.name = name
self.age = age
return self
end
-- Person এর একটি method (greet)
function Person:greet()
print("Hello, my name is " .. self.name .. " and I am " .. self.age .. " years old.")
end
-- ইনস্ট্যান্স তৈরি করা
local person1 = Person.new("Alice", 30)
local person2 = Person.new("Bob", 25)
person1:greet() -- আউটপুট: Hello, my name is Alice and I am 30 years old.
person2:greet() -- আউটপুট: Hello, my name is Bob and I am 25 years old.ব্যাখ্যা:
- Person টেবিলটি একটি ক্লাস হিসেবে কাজ করছে।
Person.newফাংশনটি একটি নতুন Person অবজেক্ট তৈরি করছে এবং এটি একটি metatable সেট করছে যাPersonক্লাসের বৈশিষ্ট্যগুলো প্রয়োগ করতে সাহায্য করে।Person:greetমেথডটি অবজেক্টের নাম এবং বয়স প্রিন্ট করার জন্য ব্যবহৃত হচ্ছে।- অবজেক্ট তৈরি করার সময়
setmetatable({}, Person)ব্যবহার করা হচ্ছে যাতে টেবিলের উপরPersonক্লাসের মেথডগুলি প্রযোজ্য হয়।
৩. Inheriting from another class
লুয়া ভাষায় Inheritance সিমুলেট করার জন্য Metatables ব্যবহার করা হয়। এখানে আমরা দেখাবো কিভাবে একটি Student ক্লাস Person ক্লাস থেকে ইনহেরিট করতে পারে।
৩.১. Inheritance উদাহরণ
-- Person ক্লাস
Person = {}
Person.__index = Person
function Person.new(name, age)
local self = setmetatable({}, Person)
self.name = name
self.age = age
return self
end
function Person:greet()
print("Hello, my name is " .. self.name .. " and I am " .. self.age .. " years old.")
end
-- Student ক্লাস (Person থেকে ইনহেরিট)
Student = setmetatable({}, Person) -- Student ক্লাস Person থেকে ইনহেরিট হচ্ছে
Student.__index = Student
function Student.new(name, age, school)
local self = Person.new(name, age) -- Person ক্লাসের constructor কল করা হচ্ছে
setmetatable(self, Student) -- Student ক্লাসের metatable সেট করা
self.school = school
return self
end
function Student:greet()
Person.greet(self) -- Person এর greet মেথড কল করা
print("I study at " .. self.school)
end
-- ইনস্ট্যান্স তৈরি করা
local student1 = Student.new("Charlie", 20, "XYZ University")
student1:greet()আউটপুট:
Hello, my name is Charlie and I am 20 years old.
I study at XYZ Universityব্যাখ্যা:
Studentক্লাসটিPersonক্লাস থেকে ইনহেরিট করছে। এটিPersonএর metatable ব্যবহার করছে, ফলেStudentটেবিলের ইনস্ট্যান্সPersonএর মেথডগুলোও ব্যবহার করতে পারছে।Student.newফাংশনে প্রথমেPerson.newফাংশনটি কল করা হয়েছে, তারপরStudentএর নিজস্ব ফিচারগুলো সেট করা হয়েছে।Student:greetমেথডেPerson.greet(self)কল করে প্রথমেPersonক্লাসের গ্রীট মেথডটি কল করা হয়েছে, তারপরStudentএর নিজস্ব ইনফরমেশন প্রিন্ট করা হয়েছে।
৪. Polymorphism in Lua (পলিমরফিজম)
লুয়া ভাষায় Polymorphism (পলিমরফিজম) বা একাধিক রূপ ধারণ করা অনেক সহজ। এটি সেই ধারণা যেখানে একাধিক ক্লাস বা অবজেক্ট একই নামের মেথডে ভিন্ন ভিন্ন আচরণ করতে পারে। একে সাধারণত মেথড ওভাররাইডিং বলা হয়।
উদাহরণ:
-- Person ক্লাস
Person = {}
Person.__index = Person
function Person.new(name)
local self = setmetatable({}, Person)
self.name = name
return self
end
function Person:speak()
print(self.name .. " is speaking!")
end
-- Student ক্লাস
Student = setmetatable({}, Person)
Student.__index = Student
function Student.new(name, school)
local self = Person.new(name)
setmetatable(self, Student)
self.school = school
return self
end
function Student:speak()
print(self.name .. " is studying at " .. self.school)
end
-- অবজেক্ট তৈরি করা
local person1 = Person.new("Alice")
local student1 = Student.new("Bob", "XYZ University")
-- polymorphism
person1:speak() -- আউটপুট: Alice is speaking!
student1:speak() -- আউটপুট: Bob is studying at XYZ Universityএখানে, Person এবং Student ক্লাসের speak মেথডে পলিমরফিজম প্রয়োগ করা হয়েছে। Student ক্লাসটি Person ক্লাসের speak মেথডটি ওভাররাইড করেছে।
সারসংক্ষেপ
- Metatables লুয়া ভাষায় Object-Oriented Design তৈরি করতে অত্যন্ত গুরুত্বপূর্ণ। এটি ক্লাস এবং অবজেক্ট সিমুলেট করতে সহায়তা করে।
- Coroutines বা ফাংশনালিজমের সাহায্যে কাস্টম methods তৈরি এবং ইনহেরিটেন্স ও পলিমরফিজম সিমুলেট করা সম্ভব।
- Metatables ব্যবহার করে লুয়া ভাষায় অবজেক্ট তৈরি, ইনহেরিটেন্স, এবং পলিমরফিজম সম্পাদন করা যায়, যা OOP এর মৌলিক কনসেপ্টগুলো কার্যকরভাবে প্রয়োগ করতে সাহায্য করে।
এই কৌশলগুলির মাধ্যমে, আপনি লুয়া ভাষায় আরও শক্তিশালী এবং পঠনযোগ্য কোড তৈরি করতে পারেন।
Read more