ইন্টারফেস (অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং)

--

Photo by Artem Sapegin on Unsplash

আজ একটা ইন্টারেস্টিং টপিক নিয়ে লিখব। ভার্সিটিতে এই নামে একটা কোর্স ছিল। সেটা অনেকের গলার কাঁটা হলেও আশা করি এই টপিক তেমন হবে না।
পিএইচপি তে ইন্টারফেস কাজ করে অনেকটা এ্যাডাপটারের মত। আমাদের ল্যাপটপের অ্যাডাপটারের কাজ কি ? এটা বাসার মেইন ভোল্টেজটাকে একটা লো ভোল্টেজে কনভার্ট করে আমাদের ল্যাপটপে সরবরাহ করে। এই ইন্টারফেসের কাজও অনেকটা এরকম।

ক্ল্যাশ রয়াল নিয়ে একটা উদাহরণ দিলে ব্যাপারটাা আরো পরিস্কার হবে। ধরা যাক আজা আমরা দুটো ট্রুপস নিয়ে খেলতে বসছি(বাস্তবে কিন্তু না) হগ রাইডার এবং মিনিয়ন। এদের দুজনেরই হেল্থ এবং টার্গেট ক্যালকুলেট করার জন্য আলাদা ফাংশন আছে। তাহলে একটা ট্রুপসের এই ডিটেইলস্ গুলো দেখার অ্যাপ্রোচ টা কেমন হবে?

অনেকটা এরকম : ফার্স্টা আমরা ক্যারেক্টার গুলোর জন্য ক্লাস এবং ফাংশনগুলো ডিফাইন করবো। তারপর নতুন ইন্সট্যান্স তৈরি করে তাদের অ্যাট্রিবিউট গুলো চেক করবো ।

class HogRider
{
public function health (){
return 100;
}

public function target (){
return "Building";
}

}
class Minion
{
public function health (){
return 70;
}
public function target (){
return "Air and ground";
}

}
$troop= new HogRider;
echo $troop->health().PHP_EOL;
echo $troop->target().PHP_EOL;

হ্যা এভাবে চেক করা যায়, কিন্তু এটা কি ভালো অ্যাপ্রোচ ? কি হবে যদি আমাদের ১০ টা নিউ ক্যারেক্টার বিল্ড করতে হয় এবং প্রতিটার জন্য ১০ টা করে ফাংশন কল করতে হয়?
তখন 100+ লাইনের কোড করতে যেয়ে ভুল করাটা সময়ের ব্যাপার।

তো যদি এরকম কিছু থাকত যে তার ভেতরে নিউ ক্যারেক্টার ইন্সট্যান্স টা দিয়ে দিলেই সে আমাদের জন্য সব করে দেবে যেমন এক্ষেত্রে ট্রুপসের ডিটেইলস গুলো বলে দেবে তাহলে আমাদের কোড অনেক অর্গানাইজড হয় এবং ভুল করার সম্ভাবনাও অনেকখানি কমে যায়। এটাই একটা ইন্টারফেসের প্রধান কাজ। আমরা একটা ইন্টারফেস ডিক্লেয়ার করতে পারি এভাবে :

interface NameOfInterface{ 
...
}

ইন্টারফেসের ভেতরে থাকবে শুধু কমন ফাংশনগুলো। ফাংশনের কোন কোডিং বা লজিক না শুধু ফাংশন নেম টাইপ আর প্যারামিটার (অনেকটা প্রোটোটাইপ ডিক্লেয়ার করার মত)।এরকম:

interface TroopsInterface{
public function health();
public function target();
}

তো আমাদের ইন্টারফেস তৈরি হয়ে গেল এখন এটাকে হগ রাইডার আর মিনিয়নের জন্য ইম্প্লিমেন্ট করতে হবে ।

class HogRider implements TroopsInterface{
...
}
class Minion implements TroopsInterface{
...
}

এখন আমরা একটা কাজ করি ট্রুপস নামের একটা ক্লাস বানাই আর এর ডিপেন্ডেন্সি হিসেবে আমাদের ইন্টারফেস টাকে সেট করি।

class Troops
{
private $troops;
public function __construct(TroopsInterface $troops){
$this->troops= $troops;
}
}

আমরা বেশ গুরুত্বপূর্ণ একটা অংশ শেষ করলাম কিন্তু। এখন যদি এই ট্রুপস কন্সট্রাক্ট করার সময় আমরা হগরাইডার পাস করি সে এক্সেপ্ট করবে আবার মিনিয়ন পাস করলেও এক্সেপ্ট করবে। আচ্ছা আগে ট্রুপস ক্লাসটা সম্পুর্ণ করি

class Troops
{
private $troops;
public function __construct(TroopsInterface $troops){
$this->troops= $troops;
}

public function details(){
echo $this->troops->health().PHP_EOL;
echo $this->troops->target().PHP_EOL;
}
}

মানে নিউ ট্রুপস বানিয়ে ডিটেইলস ফাংশনটা কল করলেই আমরা একটা ট্রুপসের হেল্থ এবং টার্গেট জানতে পারবো (এখানে PHP_EOL নিউলাইন এর জন্য )।

(new Troops(new HogRider))->details();
(new Troops(new Minion))->details();

এখানে ট্রুপসের কন্সট্রাকটরে অামরা কিন্তু ইন্টারফেস পাঠাচ্ছি না আমরা শুধু হগরাইডার বা মিনিয়নের ইন্সট্যান্স পাঠাচ্ছি। এবং এটা অটোম্যাটিক্যালি সেই ইন্সট্যান্সের হেল্থ এবং টার্গেট বলে দিচ্ছে। ব্যাপারটা কিন্তু অনেকটা এ্যাডাপটার বা কনভার্টারের মতই।

যাই হোক অনেক প্যাচাল পারলাম সবশেষে মনে হতেই পারে ইন্টারফেস ব্যাপারটাই মনে হয় একটু ভ্যাজালে। তবে একটু প্রাকটিস করলে কিন্তু ইন্টারফেসেও A+ পাওয়া যায় ;)।

full code , original post

--

--