গেট সেট ডার্ট: মিক্সিন
অবজেক্ট-ওরিয়েন্টেড প্রোগ্রামিঙে যাদের সদ্য হাতেখড়ি হয়েছে তারাও ইনহেরিট্যান্স (Inheritance) কী তা জানেন। তবুও একটু দেখা যাক:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | class Animal { bool alive; Animal reproduce(){ return new Animal(); } } class Dog extends Animal {} class Human extends Animal {} main() { var niki = new Dog(); print(niki is Dog); // >> true print(niki is Animal); // >> true var abul = new Human(); print(abul is Human); // >> true print(abul is Animal); // >> true } |
হুম! খুবই সোজা বিষয়, কুকুর তো আসলে প্রাণীই, তাই Dog
তো Animal
এরই চাইল্ড ক্লাস হবে। স্বাভাবিকভাবেই niki
নামের আমাদের কুকর কি Dog
?, বা niki
কি Animal
? দুটির উত্তরই true
। আবার আবুল নামের আমাদের মানুষটাও একইভাবে Human
ও Animal
।
কিন্তু বিশপ বললো যে…
গড নাকি শুধু মানুষকেই স্বাধীন চিন্তার ক্ষমতা দিয়েছে। মানুষকে শুধুমাত্র প্রাণী বলে প্রাণীর কাতারে নামানো অত্যন্ত গর্হিত কাজ। মাথা চুলকে আপনি আবার কোড লিখতে বসলেন:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | class Animal { bool alive; Animal reproduce(){ return new Animal(); } } class Sentient extends Animal { void think(){ print("Food, S-word, another S-word, Repeat..."); } } class Dog extends Animal {} class Human extends Sentient {} main() { var niki = new Dog(); print(niki is Dog); // >> true print(niki is Animal); // >> true print(niki is Sentient); // >> false var abul = new Human(); print(abul is Human); // >> true print(abul is Animal); // >> true print(abul is Sentient); // >> true } |
বিশপ তো মনে সুখে নাচতে নাচতে চলে গেলো। কিন্তু কম্পিউটার সায়েন্টিস্টরা কি আপনাকে ছেড়ে দেবে? এক লম্বা দাঁড়িওয়ালা, কড়া কফিখাওয়া কম্পিউটার সায়েন্টিস্ট একদিন স্বাধীন চিন্তারকারী, মানুষের মত বা তারচেয়ে শক্তিশালী চিন্তা শক্তির অধিকারী কৃত্রিম বুদ্ধিমত্তা আবিষ্কার করে ফেললো। এখন? সে তো সেন্টিয়েন্ট, কিন্তু অ্যানিম্যাল না? তাহলে কী হবে?
দারুণ! একটা বুদ্ধি এলো আপনার মাথায়! আমরা যাকে বলি কম্পোজিশন!
আপনি তরতর করে লিখে ফেললেন:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class Animal { bool alive; Animal reproduce(){ return new Animal(); } } class Sentient { void think(){ print("Food, S-word, another S-word, Repeat..."); } } class Dog extends Animal {} class Human extends Animal { Sentient sentience = new Sentient(); } class AI { Sentient sentience = new Sentient(); } main() { var abul = new Human(); abul.sentience.think(); // >> Food, S-word, another S-word, Repeat... var skynet = new AI(); skynet.sentience.think(); // >> Food, S-word, another S-word, Repeat... } |
অর্থাৎ আপনি আর Sentient
ক্লাস থেকে ইনহেরিট করছেন না। তার বদলে যাকে যাকে চিন্তা শক্তি দিতে চাচ্ছেন তাকে Sentient
ক্লাসের একটা অবজেক্ট দিচ্ছে। আমরা যে সমস্যায় পড়ে এই পদ্ধতি বেছে নিয়েছি বড় প্রোগ্রামে তেমন সমস্যায় প্রোগ্রামাররা প্রায়শই পড়েন। এর একটা সুন্দর নামও আছে, iheritance hell, আর আমাদের মুক্তির পথ ছিল কম্পোজিশন। অনেকেই তাই Composition over Inheritance নীতি মেনে চলেন। অর্থাৎ, যতটা পারা যায় ইনহেরিট না করে কম্পোজিশন করেন তারা।
এই পর্যায়ে আপনি, “আরে ভাই! সব বুঝলাম, কিন্তু মিক্সিন কই?”
কম্পোজিশন ভালো, তবে কোড দেখতে খারাপ (আমার চোখ), একটু বেশি কসরত করতে হয়, অন্তত, একটু বেশি লিখতে হয় কম্পোজিশন এলিমেন্টের কোনো মেথড বা ভেরিয়েবলে অ্যাক্সেস করতে। ডার্টে কম্পোজিশন না করেই তার সুবিধা নেওয়া যায় মিক্সিন ব্যবহার করে। মিক্সিন ব্যবহার করে উপরের কোডটি হত:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class Animal { bool alive; Animal reproduce(){ return new Animal(); } } mixin Sentient { void think(){ print("Food, S-word, another S-word, Repeat..."); } } class Dog extends Animal {} class Human extends Animal with Sentient { } class AI with Sentient { } main() { var abul = new Human(); abul.think(); // >> Food, S-word, another S-word, Repeat... var skynet = new AI(); skynet.think(); // >> Food, S-word, another S-word, Repeat... } |
আমরা Sentient
ক্লাসটিকে মিক্সিনে রূপান্তরিত করেছি। এটা করতে আমাদের শুধু ডেফিনিশনে class
এর বদলে mixin
লিখেছি। আর আমরা ক্লাসের সাথে with
কীওয়ার্ড দিয়ে মিক্সিন ব্যবহার করছি। এখন কিন্তু আমাদের abul.sentience.think()
লিখতে হচ্ছে না, বরং abul.think()
লিখতে পারছি (আবুলের চিন্তার পথে বাধা কমে গেলো)।
কিন্তু, জন্মনিয়ন্ত্রণের কী হবে?
হুম! কঠিন প্রশ্ন। এআই এর তো জন্মনিয়ন্ত্রণ করতে হয় না। আবার সব প্রাণী জন্মনিয়ন্ত্রণ করেও না। যারা চিন্তা করতে পারে তারাই ভেবে এমন একটা ব্যবস্থা করতে পারে। তো, চিন্তা করা অর্থাৎ Sentient
মিক্সিন যে সুবিধা দেয়, এবং reproduce
করা যেটা Animal
ক্লাস পারে দুটোই দরকার। কিন্তু মিক্সিনে আমরা কীকরে এই দুটি মিক্সিন ও ক্লাসকে পাবো? মিক্সিন নিজে কিন্তু ক্লাস না, ইনহেরিট্যান্সের প্রশ্নই আসে না।
আমাদের লাগবে ‘on’
on কীওয়ার্ড ব্যবহার করে আমরা অন্যান্য টাইপ ও তাদের ইন্টার্নাল প্রোপার্টিজে অ্যাক্সেস নিতে পারি। আর ক্লাস ও মিক্সিন এরাও টাইপ। অর্থাৎ আমরা লিখবো:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class Animal { bool alive; Animal reproduce(){ return new Animal(); } } mixin Sentient { void think(){ print("Food, S-word, another S-word, Repeat..."); } } mixin BirthController on Animal, Sentient { Animal reproduce(){ this.think(); print("No more S!"); return null; } } class Dog extends Animal {} class Human extends Animal with Sentient, BirthController { } class AI with Sentient { } main() { var abul = new Human(); abul.reproduce(); // >> Food, S-word, another S-word, Repeat... // >> No more S! } |
লক্ষ্য করুন, BirthController
মিক্সিনটি on কীওয়ার্ড ব্যবহার করে Animal
ক্লাস ও Sentient
মিক্সিন দুটোতেই (দুটোই লাগবে এমন কোনো কথা নেই, একটা হলেও চলত।) এক্সেস করতে পারছে। এমনকি যখন আমরা Human
ক্লাস বানাচ্ছি এটি আসলে Animal
এর reproduce
মেথডটি ওভাররাইডও করছে। একথা বলা বাহুল্য যে, যে ক্লাস বা মিক্সিনগুলোকে on কীওয়ার্ড দিয়ে মিক্সিনে ব্যবহার করা হবে মূল ক্লাস ডিক্লিয়ারেশনের সময় সেই ক্লাস থেকে ইনহেরিট ও সেই মিক্সিনগুলো ব্যবহার করতে হবে।
কেন মিক্সিন?
কেন কম্পোজিশন ভালো তা আমরা দেখেছি। তবে কম্পোজিশনের জায়গায় মিক্সিন ব্যবহারের কারন হচ্ছে এটি ইনহেরিট্যান্সের ফ্লেভর আর অ্যাসথেটিকস্ অক্ষুণ্ন রেখে কম্পোজিশনের ফ্লেক্সিবিলিটি দিচ্ছে। যা, লং-রানে রোবাস্ট ও মেইন্টেইনেবল প্রোগ্রাম লিখতে সাহায্য করবে।