7.8 জাভাস্ক্রিপ্টে প্রাইভেট প্রোপার্টি হাইড করা

অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং কনসেপ্টের সবচেয়ে গুরুত্বপূর্ণ টপিকগুলোর একটা হলো – internal ইন্টারফেস থেকে external ইন্টারফেসকে আলাদা করা। মানে কোডের কঠিন ইমপ্লিমেন্টেশন লজিকগুলোকে আলাদা করা এবং ইউজারকে শুধুমাত্র বাইরের ফাংশনালিটি দেখানো। যেকোনো সফটওয়্যার তৈরির ক্ষেত্রে আমাদের এই কনসেপ্ট জানা দরকার।

চলুন একটা বাস্তব উদাহরণ দিয়ে বোঝা যাক। আমরা কফি মেশিনের সাথে সবাই পরিচিত। কফি বানানোর জন্য আমাদের সাধারণত কি করতে হয়? উপরে দিয়ে কফি, দুধ আর চিনি দিয়ে কয়েকটা বাটনে টিপ দিতে হয়, খুবই সহজ তাইনা?

coffee machine outside

বাহির থেকে দেখতে খুব সিম্পল মনে হলেও ভিতরে দেখতে অনেকটা নিচের ছবির মতো।

coffee machine inside

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

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

অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং এ, প্রোপার্টি আর মেথডকে সাধারণত দুই ভাগ্যে ভাগ করা যায়ঃ

Internal interface – যা ক্লাসের অন্যান্য মেথড থেকে এক্সেস করা যাবে, কিন্তু ক্লাসের বাইরে থেকে এক্সেস করা যাবেনা। Internal প্রোপার্টিকে private প্রোপার্টিও বলা হয়।
External interface – ক্লাসের ভিতরে অথবা বাইরে, যেকোনো যায়গা থেকে এক্সেস করা যাবে। External প্রোপার্টিকে public প্রোপার্টিও বলা হয়।

এগুলোকে আমরা আমাদের কফি মেশিনের সাথে তুলনা করতে পারি। ভিতরের জটিল মেশিন হলো internal ইন্টারফেস, আর বাইরের বাটন সুইচ এগুলা হলো external ইন্টারফেস।

কিছু কিছু ল্যাঙ্গুয়েজে protected ফিল্ডও আছে। যা শুধুমাত্র ক্লাসের ভিতরে থেকে এবং যেসকল অবজেক্ট ক্লাস থেকে ইন্সট্যান্স তৈরি করে বানানো হয়েছে তারাই এক্সেস করতে পারবে।
জাভাস্ক্রিপ্টে ল্যাংগুয়েজ লেভেলে protected ফিল্ড বলতে কিছু নেই। কিন্তু আমরা প্রায়ই protected ফিল্ড নিয়ে কাজ করব।

Protected প্রোপার্টিগুলো সাধারণত _ (underscore) দিয়ে শুরু করা হয়। এটা কোনো বাধ্যতামূলক জিনিস না, কিন্তু জাভাস্ক্রিপ্ট প্রোগ্রামাররা এই নিয়ম মেনে চলে। নিচের কোডটি খেয়াল করি।

class CoffeeMachine {
   waterAmount = 0;
   sugarAmount = 0;
   constructor(power) {
     this.power = power;
     console.log("Created a coffee machine with power: "+power)
   }
}

// কফি মেশিন থেকে নতুন কফি অবজেক্ট তৈরি
let coffee = new CoffeeMachine(100);

// কফিতে পানির পরিমাণ
coffee.waterAmount = 200;

 

এখানে আমরা CoffeeMachine ক্লাস থেকে নতুন একটি coffee নামে ইন্সট্যান্স তৈরি করেছি। আমরা চাইলেই CoffeeMachine ক্লাসের প্রোপার্টিগুলা যেমন waterAmount বা sugarAmount এর মান পরিবর্তন করতে পারি। কারণ বর্তমানে এগুলা public। চলুন আমরা sugarAmount প্রোপার্টিকে protected করে দেখি যাতে বাহির থেকে চাইলেই ইচ্ছামত কেউ পরিবর্তন করতে না পারে। আমরা এখানে getter এবং setter ব্যবহার করে ভ্যালু পরিবর্তন আর ভ্যালু এক্সেস করব। নিচের কোডটি খেয়াল করেনঃ

class CoffeeMachine {
   waterAmount = 0;
   _sugarAmount = 0;
   set sugarAmount(value) {
     if (value < 0) {
       value = 0;
     }
     this._sugarAmount = value;
  }
  get sugarAmount(){
    return this._sugarAmount;
  }

  constructor(power) {
    this.power = power;
    console.log("Created a coffee machine with power: "+power)
  }

}

// কফি মেশিন থেকে নতুন কফি অবজেক্ট তৈরি
let coffee = new CoffeeMachine(100);

// কফিতে চিনির পরিমাণ
coffee.sugarAmount = -100;
console.log(coffee.sugarAmount) // আউটপুটঃ 0

 

এখন প্রোপার্টি এক্সেস আমাদের কন্ট্রোলে আছে। কেউ চাইলেই এখন sugarAmount এর মান শূন্য থেকে কম সেট করতে পারবে না। এভাবেই চাইলে আমরা ক্লাসের কোনো প্রপার্টিকে protected করতে পারি।

Protected ফিল্ড ইনহেরিট হয়। মানে প্যারেন্ট ক্লাসকে ইনহেরিট করে যেসকল চাইল্ড ক্লাস সবাই প্যারেন্টের protected প্রোপার্টি পেয়ে যাবে।

এখন আমরা private প্রোপার্টি নিয়ে নিয়ে জানব। এটি এখনো একটি তৃতীয় স্টেজের প্রপোজাল। কিন্তু Babel এর লেটেস্ট ভার্শনের সহায়তায় আমরা তা ব্যবহার করতে পারব।

Private প্রোপার্টিগুলো # দিয়ে শুরু করতে হয়। শুধুমাত্র ক্লাসের মধ্যে থেকেই এদের এক্সেস করা যায়। নিচের কোডটি খেয়াল করেনঃ

class CoffeeMachine {
   #waterAmount = 0;
   set setWaterAmount(value) {
     this.#waterAmount = value;
   }
}

let coffee = new CoffeeMachine();
coffee.setWaterAmount = 100;
coffee.#waterAmount;        // SyntaxError: Private field '#waterAmount' must be declared in an enclosing class

 

আমরা #waterAmount নামে একটি প্রাইভেট প্রপার্টি সেট করেছি। কেউ চাইলেই ক্লাসের বাইরে থেকে তা সরাসরি এক্সেস করতে পারবেনা, তার জন্য আমাদের getter/setter মেথডের সহায়তা নিতে হবে। নিচের উদাহরণটি দেখলে ব্যপারটা ক্লিয়ার হয়ে যাবে।

class CoffeeMachine {
   #waterAmount = 0;
   set waterAmount(value) {
     this.#waterAmount = value;
   }
   get waterAmount() {
     return this.#waterAmount;
   }
}

let coffee = new CoffeeMachine();
coffee.waterAmount = 10;
console.log(coffee.waterAmount);

 

আমরা জাভাস্ক্রিপ্টের পাবলিক, প্রাইভেট আর প্রোটেক্টেড প্রোপার্টিগুলা সম্পর্কে জানলাম। যা অত্যন্ত গুরুত্বপূর্ণ একটি কনসেপ্ট।