# Encapsulation and Abstraction

## **Encapsulation**

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

![](https://1856353139-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MClo3nC-1US0rbK8Qau%2F-MQwR29aMuImdjSxEO0H%2F-MQwsQ7gjL6nq9DMTneG%2FScreenshot%20from%202021-01-13%2016-08-20.png?alt=media\&token=cec353d5-1b80-44f0-9296-3c4823380223)

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

{% tabs %}
{% tab title="Example class-object code C++" %}

```cpp
// 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;
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```cpp
your name is James
your salary is 15000
your name is James
your salary is -10000
```

{% endtab %}
{% endtabs %}

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

{% tabs %}
{% tab title="Example Encapsulation code C++" %}

```cpp
// 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;
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```cpp
your name is James
your salary is 18000
your name is Conun
your salary is 0
```

{% endtab %}
{% endtabs %}

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

{% hint style="success" %}
**คำถาม** ทำไมการประกาศเมดธอด getSalary() ถึงใช้ int แทนการใช้ void ?

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

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

แหล่งอ้างอิง :: <https://www.w3schools.com/cpp/cpp_functions.asp>
{% endhint %}

## **Abstraction**

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

### &#x20;1. Abstraction โดยใช้ Class

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

{% tabs %}
{% tab title="Example code <Abstraction using Classes> C++" %}

```cpp
// 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();
   
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```cpp
EmpId = 1       Name = Ved
Employee Salary = 17245.4
```

{% endtab %}
{% endtabs %}

&#x20;

### 2. Abstraction โดยใช้ไฟล์ Header&#x20;

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

{% tabs %}
{% tab title="Example code <Abstraction using Header file> C++" %}

```cpp
// 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; 
} 
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```cpp
36
```

{% endtab %}
{% endtabs %}

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

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

* Abstraction โดยใช้ Class -> ต้องประกาศ class เพื่อเรียกใช้เมดธอดภายใน class นั้น
* Abstraction โดยใช้ไฟล์ Header -> ไม่จำเป็นต้องประกาศ class สามารถเรียกใช้ฟังก์ชันที่มีอยู่ในไฟล์ Header &#x20;
  {% endhint %}

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

* <https://www.softwaretestinghelp.com/encapsulation-in-cpp/>
* <https://www.softwaretestinghelp.com/data-abstraction-in-cpp/>
