Object Oriented Programming-এ Encapsulation বা এনক্যাপসুলেশন হলো data এবং সেই data-এর সঙ্গে কাজ করা method-গুলোকে একটি class-এর মধ্যে একত্রে রাখা এবং data কীভাবে access বা পরিবর্তন করা যাবে তা নিয়ন্ত্রণ করার ধারণা।
সহজভাবে বললে, object-এর internal data সরাসরি পরিবর্তন না করে নির্দিষ্ট method বা property-এর মাধ্যমে নিয়ন্ত্রিতভাবে ব্যবহার করার সুযোগ দেওয়া হয়। JavaScript-এর class, private field, getter এবং setter ব্যবহার করে Encapsulation তৈরি করা যায়।
Encapsulation = Data + Methods একসঙ্গে রাখা এবং Data Access নিয়ন্ত্রণ করা।উদাহরণ হিসেবে একটি Bank Account-এর balance সরাসরি পরিবর্তন না করে deposit() ও withdraw() method-এর মাধ্যমে পরিবর্তন করা যেতে পারে।
class BankAccount { #balance = 0; deposit(amount) { this.#balance += amount; } getBalance() { return this.#balance; } } const account = new BankAccount(); account.deposit(1000); console.log(account.getBalance());
আধুনিক JavaScript-এ class-এর private field তৈরি করতে variable-এর নামের শুরুতে # ব্যবহার করা যায়। Private field class-এর বাইরে থেকে সরাসরি access করা যায় না।
এর ফলে class-এর গুরুত্বপূর্ণ data সরাসরি পরিবর্তন করা থেকে বাইরের code-কে বিরত রাখা যায়। প্রয়োজন অনুযায়ী public method-এর মাধ্যমে data ব্যবহার করা যায়।
Private field: #property — class-এর বাইরে সরাসরি access করা যায় না।নিচের উদাহরণে #balance private field হিসেবে রাখা হয়েছে।
class Account { #balance = 5000; getBalance() { return this.#balance; } } const account = new Account(); console.log(account.getBalance());
JavaScript class-এ private method তৈরি করাও সম্ভব। Private method-এর নামের শুরুতে # ব্যবহার করা হয় এবং এটি class-এর বাইরে থেকে সরাসরি call করা যায় না।
Internal calculation বা গুরুত্বপূর্ণ processing-এর জন্য private method ব্যবহার করা যায়। এতে class-এর implementation বাইরে থেকে নিয়ন্ত্রিত থাকে।
Private method-এর syntax: #methodName() { ... }নিচের উদাহরণে #calculate() একটি private method এবং getTotal() একটি public method।
class Calculator { #calculate(a, b) { return a * b; } getTotal(a, b) { return this.#calculate(a, b); } } const calculator = new Calculator(); console.log(calculator.getTotal(10, 5));
Getter ব্যবহার করে class-এর internal data সরাসরি প্রকাশ না করে একটি property-এর মতো করে নির্দিষ্ট value পাওয়া যায়। এটি encapsulation-এর একটি গুরুত্বপূর্ণ ব্যবহার।
Getter-এর মাধ্যমে data কীভাবে বাইরে থেকে পাওয়া যাবে তা class-এর ভিতর থেকে নিয়ন্ত্রণ করা যায়।
Getter ব্যবহার করলে method-এর result property-এর মতো access করা যায়।নিচের উদাহরণে #name private রাখা হয়েছে এবং name getter-এর মাধ্যমে সেটি পড়া হচ্ছে।
class User { #name = "Anik"; get name() { return this.#name; } } const user = new User(); console.log(user.name);
Setter ব্যবহার করে কোনো property-তে value assign করার সময় নির্দিষ্ট validation বা business rule প্রয়োগ করা যায়। এতে internal data নিরাপদ ও নিয়ন্ত্রিতভাবে পরিবর্তন করা সম্ভব।
বাইরের code সাধারণ assignment-এর মতো value সেট করলেও setter-এর ভিতরের নিয়ম অনুযায়ী data পরিবর্তিত হয়।
Setter = Data পরিবর্তনের সময় controlled logic প্রয়োগ।নিচের উদাহরণে age-এর value 0 বা তার বেশি হলে তবেই #age পরিবর্তন করা হচ্ছে।
class Person { #age = 0; set age(value) { if (value >= 0) { this.#age = value; } } get age() { return this.#age; } } const person = new Person(); person.age = 25; console.log(person.age);
Encapsulation-এর ক্ষেত্রে internal data সরাসরি পরিবর্তন না করে public method-এর মাধ্যমে পরিবর্তন করা একটি প্রচলিত পদ্ধতি। Method-এর ভিতরে প্রয়োজনীয় validation ও নিয়ম রাখা যায়।
এতে object-এর data কীভাবে পরিবর্তন হবে তার উপর class-এর নিয়ন্ত্রণ বজায় থাকে।
Public method = Controlled Data Modification-এর একটি সহজ উপায়।নিচের উদাহরণে deposit() method-এর মাধ্যমে balance বাড়ানো হচ্ছে।
class Wallet { #balance = 0; deposit(amount) { if (amount > 0) { this.#balance += amount; } } getBalance() { return this.#balance; } } const wallet = new Wallet(); wallet.deposit(2000); console.log(wallet.getBalance());
Encapsulation ব্যবহার করে class-এর internal data পরিবর্তনের আগে validation করা যায়। এতে ভুল বা অপ্রত্যাশিত data গ্রহণের সম্ভাবনা কমানো যায়।
Validation logic class-এর method বা setter-এর মধ্যে রাখলে application-এর বিভিন্ন জায়গায় একই নিয়ম আলাদাভাবে লিখতে হয় না।
Encapsulation-এর মাধ্যমে Data Access এবং Validation একই জায়গায় সংগঠিত করা যায়।নিচের উদাহরণে product-এর price negative হলে সেটি গ্রহণ করা হচ্ছে না।
class Product { #price = 0; set price(value) { if (value >= 0) { this.#price = value; } } get price() { return this.#price; } } const product = new Product(); product.price = 500; console.log(product.price);
Getter ব্যবহার করে এমন property তৈরি করা যায় যেটি বাইরে থেকে পড়া যাবে কিন্তু সরাসরি পরিবর্তন করার public setter থাকবে না। এটি read-only data ব্যবহারের একটি সহজ উপায়।
Internal field private থাকায় বাইরের code সরাসরি সেটি পরিবর্তন করতে পারে না।
Private field + Getter = Controlled বা Read-only Data-এর একটি পদ্ধতি।নিচের উদাহরণে accountId শুধু getter-এর মাধ্যমে পাওয়া যাচ্ছে এবং বাইরে থেকে সরাসরি পরিবর্তন করা যাচ্ছে না।
class Account { #accountId = "ACC-1001"; get accountId() { return this.#accountId; } } const account = new Account(); console.log(account.accountId);
Encapsulation বড় program-এ data ও related methods-কে সুসংগঠিত রাখতে সাহায্য করে। Internal data সরাসরি access না করার ফলে code-এর বিভিন্ন অংশের মধ্যে dependency কমানো যায়।
এতে validation, maintenance এবং ভবিষ্যতে internal implementation পরিবর্তন করা তুলনামূলক সহজ হতে পারে।
Encapsulation-এর মূল লক্ষ্য হলো data ও implementation-কে একটি নির্দিষ্ট boundary-এর মধ্যে রাখা এবং access নিয়ন্ত্রণ করা।একটি class-এর ভিতরের implementation পরিবর্তন করলেও public interface একই রাখা সম্ভব হলে অন্য code-এর উপর প্রভাব কমতে পারে।
class Employee { #salary = 30000; getSalary() { return this.#salary; } increaseSalary(amount) { if (amount > 0) { this.#salary += amount; } } } const employee = new Employee(); employee.increaseSalary(5000); console.log(employee.getSalary());
Encapsulation এবং Abstraction পরস্পরের সঙ্গে সম্পর্কিত হলেও তাদের লক্ষ্য এক নয়। Encapsulation data ও implementation-কে class-এর মধ্যে সংগঠিত এবং access নিয়ন্ত্রিত রাখে। Abstraction ব্যবহারকারীর কাছে প্রয়োজনীয় functionality প্রকাশ করে এবং অপ্রয়োজনীয় implementation details আড়াল করে।
বাস্তব JavaScript application-এ private field, getter, setter এবং public method একসঙ্গে ব্যবহার করে দুই ধারণাই প্রয়োগ করা যায়।
মনে রাখুন: Encapsulation focuses on containing and controlling data; Abstraction focuses on exposing necessary functionality.নিচের উদাহরণে #balance private data হিসেবে encapsulated এবং deposit() ও getBalance() public functionality হিসেবে প্রকাশ করা হয়েছে।
class BankAccount { #balance = 0; deposit(amount) { if (amount > 0) { this.#balance += amount; } } getBalance() { return this.#balance; } } const account = new BankAccount(); account.deposit(5000); console.log(account.getBalance());