Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> C++

Encapsulation ใน C++ (การห่อหุ้มข้อมูล)

Encapsulation (การห่อหุ้ม) เป็นหลักการสำคัญของ OOP ที่ รวม Data (Attributes) และ Methods (Behaviors) ไว้ในหน่วยเดียวคือ Class และ ซ่อนรายละเอียดการทำงานภายใน (Implementation Details) ไว้จากภายนอก

หลักการหลัก

  1. Data Hiding: ทำ Data Members เป็น private
  2. Controlled Access: ให้เข้าถึงผ่าน public Methods (Getters/Setters)
  3. Validation: ตรวจสอบความถูกต้องก่อนตั้งค่า
  4. Abstraction: ผู้ใช้ไม่ต้องรู้ว่าเก็บข้อมูลยังไง คำนวณยังไง

โค้ดตัวอย่าง: กล่องสี่เหลี่ยม (Box Volume)

#include <iostream>
using namespace std;

class Box {
private:
    double length, width, height;  // Data Hiding
    
public:
    // Constructor
    Box(double l = 1, double w = 1, double h = 1) 
        : length(l), width(w), height(h) {}
    
    // Setters with Validation
    void setLength(double l) {
        if (l > 0) length = l;
        else cout << "Length must be positive!" << endl;
    }
    
    void setWidth(double w) {
        if (w > 0) width = w;
        else cout << "Width must be positive!" << endl;
    }
    
    void setHeight(double h) {
        if (h > 0) height = h;
        else cout << "Height must be positive!" << endl;
    }
    
    // Getters
    double getLength() const { return length; }
    double getWidth() const { return width; }
    double getHeight() const { return height; }
    
    // Business Logic
    double getVolume() const { return length * width * height; }
    double getSurfaceArea() const { return 2 * (length*width + width*height + height*length); }
    
    void display() const {
        cout << "Box [" << length << " x " << width << " x " << height << "]" << endl;
        cout << "Volume: " << getVolume() << endl;
        cout << "Surface Area: " << getSurfaceArea() << endl;
    }
};

int main() {
    Box box1(5, 3, 2);
    box1.display();
    
    cout << "--- Change dimensions ---" << endl;
    box1.setLength(10);
    box1.setWidth(-5);  // Validation จะป้องกัน
    box1.setHeight(4);
    box1.display();
    
    return 0;
}

ผลลัพธ์

Box [5 x 3 x 2]
Volume: 30
Surface Area: 62
--- Change dimensions ---
Width must be positive!
Box [10 x 3 x 4]
Volume: 120
Surface Area: 164

ข้อดีของ Encapsulation

ประโยชน์ คำอธิบาย
Data Integrityป้องกันค่าไม่ถูกต้อง (Validation ใน Setters)
Flexibilityเปลี่ยน Implementation ภายในได้โดยไม่กระทบ Code ภายนอก
Securityควบคุมว่าใคร Read/Write ได้บ้าง
Maintainabilityแก้ Bug/เพิ่ม Feature ใน Class เดียว
Reusabilityนำ Class ไปใช้งานซ้ำได้ง่าย
Testingทดสอบ Class แยกได้ (Unit Test)

Encapsulation vs Abstraction

Encapsulation (การห่อหุ้ม)

  • How - ซ่อน "รายละเอียดการทำงาน"
  • ระดับ: Implementation Level
  • เครื่องมือ: Access Modifiers (private/public)
  • ตัวอย่าง: private data + public getters/setters

Abstraction (การสรุปทั่วไป)

  • What - แสดง "สิ่งที่จำเป็น" เท่านั้น
  • ระดับ: Design/Interface Level
  • เครื่องมือ: Abstract Class, Interface, Pure Virtual
  • ตัวอย่าง: Abstract Class Shape → draw()

การออกแบบ Class ที่ดี (Class Design Principles)


// ✓ Good Encapsulation
class BankAccount {
private:
    string accountNumber;
    double balance;           // Private - ควบคุมผ่าน Methods
    vector<Transaction> history;
    
public:
    BankAccount(string acc) : accountNumber(acc), balance(0) {}
    
    void deposit(double amount) {     // Business Logic
        if (amount > 0) {
            balance += amount;
            history.push_back({amount, "Deposit"});
        }
    }
    
    bool withdraw(double amount) {    // Business Logic + Validation
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            history.push_back({-amount, "Withdraw"});
            return true;
        }
        return false;
    }
    
    double getBalance() const { return balance; }  // Read-only
    void printStatement() const;  // Complex operation
};

// ✗ Bad Encapsulation
class BadAccount {
public:
    double balance;  // ใครก็แก้ได้ ไม่มี Validation
};
// main() { BadAccount a; a.balance = -1000000; }  // ผิดได้!

Getter/Setter Patterns


// 1. Simple Getter/Setter
int getValue() const { return value; }
void setValue(int v) { value = v; }

// 2. Read-only Property (Getter only)
const string& getName() const { return name; }

// 3. Write-only (Setter only) - นادر
void setPassword(const string& pwd) { passwordHash = hash(pwd); }

// 4. Computed Property (ไม่เก็บตัวแปร)
double getArea() const { return width * height; }

// 5. Fluent Interface (Chaining)
Box& setLength(double l) { length = l; return *this; }
Box& setWidth(double w) { width = w; return *this; }
// ใช้: box.setLength(10).setWidth(5).setHeight(3);