Class Encapsulation

Encapsulation (الكبسلة) هو مبدأ في OOP يعني إخفاء تفاصيل البيانات الداخلية للكائن (object) بحيث لا يمكن التلاعب بها مباشرة من خارج الكائن.

هذا يجعل الكائنات:

  • أكثر أمانًا
  • أسهل في التحكم
  • مرنة للتطوير والصيانة
✅ في JavaScript، يتم تحقيق الـ Encapsulation بـ:
  1. الخصائص الخاصة (Private properties) باستخدام #
  2. الدوال الخاصة (Private methods) أيضًا باستخدام #
  3. استخدام Getters / Setters للتحكم في الوصول.

🧪 أولًا: الخصائص العامة (بدون Encapsulation)

class User {
  constructor(name) {
    this.name = name;
  }
}

let user1 = new User("Ali");
console.log(user1.name); // Ali

user1.name = "Hacker 😈"; // يمكن تغييره مباشرة
console.log(user1.name); // Hacker 😈
JavaScript

❌ غير آمن: أي شخص يمكنه تعديل البيانات من الخارج.

🟢 الآن: Encapsulation باستخدام الخصائص الخاصة #

class User {
  #name; // خاصية خاصة

  constructor(name) {
    this.#name = name;
  }

  getName() {
    return this.#name; // getter
  }

  setName(newName) {
    if (newName.length > 2) {
      this.#name = newName;
    } else {
      console.log("❌ الاسم قصير جدًا");
    }
  }
}

let user1 = new User("Ali");

console.log(user1.getName()); // ✅ Ali

user1.setName("Mo"); // ✅ تغيير مقبول
console.log(user1.getName()); // Mo

user1.setName("A"); // ❌ الاسم قصير جدًا

console.log(user1.#name); // ❌ Error: private field
JavaScript
✅ فوائد Encapsulation:
الفائدةالشرح
🛡️ الأمانلا يمكن الوصول مباشرة إلى البيانات الحساسة
📏 التحكم في التعديلاتباستخدام setters يمكنك فرض شروط
🧼 سهولة التحديث والصيانةيمكنك تغيير المنطق الداخلي دون تأثير خارجي
🧪 التقليل من الأخطاءلأن التعامل يتم فقط عبر واجهات محددة

🛠️ استخدم get و set (الصيغة المختصرة):

class Product {
  #price;

  constructor(price) {
    this.#price = price;
  }

  get price() {
    return this.#price;
  }

  set price(value) {
    if (value > 0) {
      this.#price = value;
    } else {
      console.log("❌ السعر يجب أن يكون أكبر من صفر");
    }
  }
}

let p = new Product(100);
console.log(p.price); // 100

p.price = 200;
console.log(p.price); // 200

p.price = -50; // ❌ السعر يجب أن يكون أكبر من صفر
JavaScript
🧠 ملاحظات مهمة:
  • الخصائص الخاصة # لا يمكن الوصول لها من الخارج.
  • get و set تجعل واجهة الكائن سهلة الاستخدام مثل الخصائص العادية.
  • هذه الميزات مدعومة في جميع المتصفحات الحديثة (ES2022+)

📦 مثال عملي واقعي (حساب بنكي):

class BankAccount {
  #balance;

  constructor(initialBalance) {
    this.#balance = initialBalance;
  }

  deposit(amount) {
    if (amount > 0) this.#balance += amount;
  }

  withdraw(amount) {
    if (amount <= this.#balance) {
      this.#balance -= amount;
    } else {
      console.log("❌ لا يوجد رصيد كافٍ");
    }
  }

  get balance() {
    return this.#balance;
  }
}

let acc = new BankAccount(1000);
acc.deposit(500);
acc.withdraw(300);
console.log(acc.balance); // 1200

acc.withdraw(2000); // ❌ لا يوجد رصيد كافٍ
JavaScript

💬 مثال خاطئ بدون encapsulation:

class BankBad {
  constructor(balance) {
    this.balance = balance;
  }
}

let bad = new BankBad(1000);
bad.balance = -999999; // ❌ تلاعب مباشر!
JavaScript

→ هذا مثال على كود ضعيف الأمان.

✅ خلاصة:
المفهومالتفاصيل
Encapsulationإخفاء البيانات داخل الكلاس
الخصائص الخاصةباستخدام #name
الوصول الآمنعبر get و set
فائدتهحماية البيانات وتنظيم الكود