Encapsulation and Abstraction

Encapsulation

Encapsulation คือ การรวมข้อมูลและเมดธอดที่ดำเนินการกับข้อมูลนี้เข้าเป็นหน่วยเดียว โดยจะซ่อนข้อมูลไม่ให้เข้าถึงได้โดยตรง แต่จะอนุญาติให้เมดธอดภายใน class เดียวกันสามารถเข้าถึงข้อมูลนั้นได้ เพื่อป้องกันการเข้าถึงข้อมูลจากภายนอกและการนำไปใช้ในทางที่ผิด

อย่างที่ทราบกันว่า class ประกอบไปด้วยสมาชิกตัวแปรและเมดธอด ซึ่งข้อมูลภายใน class ถูกกำหนดขอบเขตการใช้งานเป็น public เพื่อให้สามารถเข้าถึงข้อมูลจากภายนอก class นั่นหมายความว่า object ในโปรแกรม สามารถเข้าถึงตัวแปรเพื่อเปลี่ยนแก้ไขข้อมูลได้โดยตรง ดังตัวอย่างต่อไปนี้

// oop_p2_1.cpp
#include <iostream>
#include <string>
using namespace std;

class Employee{
    public:
    int id;
    string name;
    double salary;
};

int main(){
    Employee emp1;
    emp1.id = 1;
    emp1.name = "James";
    emp1.salary = 15000;
    
    cout << "your name is " << emp1.name << endl;
    cout << "your salary is " << emp1.salary << endl;

    emp1.salary = -10000;
    
    cout << "your name is " << emp1.name << endl;
    cout << "your salary is " << emp1.salary << endl;
}
your name is James
your salary is 15000
your name is James
your salary is -10000

เพื่อป้องการเข้าถึงข้อมูลจากภายนอก class จึงใช้การกำหนดขอบเขตการเข้าถึงของข้อมูลเป็น private ทำให้ object อื่น ๆ ไม่สามารถเข้าถึงข้อมูลนั้นได้ วิธีนี้เรียกว่า การซ่อนข้อมูล แต่ข้อเสียของการกำหนดขอบเขตการเข้าถึงของข้อมูลเป็น private คือ ไม่สามารถนำข้อมูลออกมาแสดงผลหรือนำมาใช้งานได้ จึงต้องหาช่องทางอื่นในการเข้าถึงข้อมูลที่สามารถควบคุมความถูกต้องของข้อมูลนั้นได้ คือ การเข้าถึงข้อมูลผ่านการเรียกใช้เมธอด ดังตัวอย่างต่อไปนี้

// oop_p2_2.cpp
#include <iostream>
#include <string>
using namespace std;

class Employee{
    private:
    double salary;
    
    public:
    int id;
    string name;

    void setSalary(double base){
    if(base >= 15000 && base <= 100000 ){
        salary = base;
        } else {
            salary = 0;
        }
    }

    int getSalary(){
        return salary;
    }
};

int main(){
    Employee emp1;
    emp1.id = 1;
    emp1.name = "James";
    emp1.setSalary(18000);
    
    cout << "your name is " << emp1.name << endl;
    cout << "your salary is " << emp1.getSalary() << endl;

    emp1.name = "Conun";
    emp1.setSalary(1000000);
    
    cout << "your name is " << emp1.name << endl;
    cout << "your salary is " << emp1.getSalary() << endl;
}
your name is James
your salary is 18000
your name is Conun
your salary is 0

จากตัวอย่างจะเห็นได้ว่าตัวแปร salary เป็นตัวแปรที่ถูกซ่อนด้วยการกำหนดขอบเขตการใช้งานเป็น private ทำให้ไม่สามารถเรียกใช้จากภายนอก class แต่ตัวแปรนี้สามารถเข้าถึงได้จากเมดธอด getSalary() และ setSalary() ที่มีอยู่ภายใน class เท่านั้น โดยที่เมดธอด getSalary() จะรับพารามิเตอร์ (parameter) ตัวเลขเข้ามาพิจารณาในเงื่อนไข หากเงื่อนไขเป็นจริง จะทำการเก็บค่านั้นลงในตัวแปร salary แต่ถ้าเงื่อนไขเป็นเท็จ จะเก็บค่า 0 ลงใน ตัวแปร salary แทนค่าที่รับมา ส่วนเมดธอด getSalary() จะทำหน้าที่ในการนำค่าที่ถูกเก็บไว้ในตัวแปร salary มาแสดงผล

คำถาม ทำไมการประกาศเมดธอด getSalary() ถึงใช้ int แทนการใช้ void ?

คำตอบ void คือ การประกาศฟังก์ชันที่ไม่มีการส่งค่าคืน

int คือ การประกาศฟังก์ชันที่ส่งค่าคืนเป็นตัวเลข

แหล่งอ้างอิง :: https://www.w3schools.com/cpp/cpp_functions.asp

Abstraction

การให้ข้อมูลที่จำเป็นหรือข้อมูลที่ต้องการให้รู้แก่ภายนอก class โดนใช้หลักแนวคิดจาก Encapsulation แต่จะแตกต่างกันที่ Encapsulation จะซ่อนข้อมูลหรือตัวแปรไม่ให้เข้าถึงได้โดยตรง ส่วน Abstraction จะซ่อนกระบวนการทำงานหรือเมดธอดที่สำคัญบางส่วนไม่ให้เข้าถึงได้โดยตรง หมายความว่า ผู้ใช้จะสามารถเรียกใช้ได้เฉพาะเมดธอดที่ถูกกำหนดเป็น public ทั้งนี้ Abstraction มีการใช้งานอยู่ 2 แบบ คือ

1. Abstraction โดยใช้ Class

ตัวอย่างเช่น การเขียนโปรแกรมคำนวณรายได้พนักงานของบริษัทแห่งหนึ่ง ผู้ใช้สามารถเรียกใช้ได้แค่เมดธอด display() ที่ใช้ในการแสดงผลเท่านั้น เนื่องจากเมดธอดที่ใช้ในการคำนวณรายได้เป็นส่วนที่ไม่ได้การให้ถูกเข้าถึง

// oop_p2_3.cpp
#include <iostream>
#include <string>
using namespace std;
class employee{
   int empId;
   string name;
   double salary,basic,allowances;
  
   double calculateSalary(int empId){
   salary = basic+allowances-1000;
   return salary;
}
public:
employee(int empId, string name,double basic,double allowances):
empId(empId),name(name),basic(basic),allowances(allowances){
   calculateSalary(empId);
}
  
void display(){
  
   cout<<"EmpId = "<<empId<<"\tName = "<<name<<endl;
   cout<<"Employee Salary = "<<salary<<endl;
  
}
};
int main()
{
   employee emp(1,"Ved",15000,3245.43);
   emp.display();
   
}
EmpId = 1       Name = Ved
Employee Salary = 17245.4

2. Abstraction โดยใช้ไฟล์ Header

ตัวอย่างเช่น การเรียกใช้งานฟังก์ชัน pow () ที่มีอยู่ใน math.h เมื่อผู้ใช้ต้องการคำนวณเลขยกกำลัง ผู้ใช้สามารถเรียกฟังก์ชัน pow() ที่มีอยู่ใน math.h และส่งตัวเลขเป็นอาร์กิวเมนต์ ฟังก์ชันจะทำการคำนวณผลลัพธ์และส่งผลลัพธ์ออกมาโดยที่ผู้ใช้ไม่ทราบอัลกอริทึมการคำนวณกำลังของตัวเลขภายในฟังก์ชัน

// oop_p2_4.cpp
#include <iostream> 
#include <math.h> 
using namespace std; 

int main() 
{ 
    int x = 6, y = 2; 
  
    int result = pow(x, y); 
    cout << result << endl;
  
    return 0; 
} 
36

ความเหมือนระหว่างการใช้งานทั้ง 2 แบบ คือ การให้ข้อมูลที่จำเป็นแก่ภายนอก class ให้รับรู้ว่ามีเมดธอดอะไรที่ควรรู้และสามารถเรียกใช้ได้บ้าง

ความแตกต่างระหว่างการใช้งานทั้ง 2 แบบ คือ

  • Abstraction โดยใช้ Class -> ต้องประกาศ class เพื่อเรียกใช้เมดธอดภายใน class นั้น

  • Abstraction โดยใช้ไฟล์ Header -> ไม่จำเป็นต้องประกาศ class สามารถเรียกใช้ฟังก์ชันที่มีอยู่ในไฟล์ Header

แหล่งที่มาเพิ่มเติม

Last updated

Assoc. Prof. Wiroon Sriborrirux, Founder of Advance Innovation Center (AIC) and Bangsaen Design House (BDH), Electrical Engineering Department, Faculty of Engineering, Burapha University