Page cover image

Abstract classes

หฤณชนก พนมวรชัย 650710592

Abstract classes คือ ...

คลาสนามธรรม(abstract method) เป็นคลาสในรูปแบบภาษาโปรแกรมเชิงวัตถุ เรามักสร้าง Abstract class ไว้เป็นต้นแบบเพื่อให้คลาสที่มาสืบทอดมีแบบแผนหรือแนวทางไปในทางเดียวกัน เราจะเรียกคลาส Abstract ว่าคลาสแม่(parent class) และคลาสที่มาสืบทอดคุณสมบัติว่าคลาสลูก(subclass) โดยภายในคลาสจะกำหนดเพียงเมดธอดตั้งต้นจะไม่มีการกำหนดเนื้อหาข้างในเมดธอดเอาไว้เพราะจะเป็นหน้าที่ของคลาสที่มาสืบทอดต้องกำหนดเนื้อหาข้างในเมดธอดให้สมบูรณ์

Abstract class in C#

ในภาษา C# มีข้อกำหนดว่าชื่อของคลาสและชื่อเมดธอดของ Abstract class ต้องมี keyword ว่า abstract

using System;

// Abstract class
public abstract class Pokemon{

    public abstract void typeWater(); // Abstract method
    
}

Abstract method

Abstract class สามารถมีทั้งเมดธอดที่เป็น Abstract method และไม่เป็นก็ได้เมดธอดที่ไม่มีการกำหนดเนื้อหาข้างในเรียกว่า Abstract method ส่วนเมดธอดที่มีการกำหนดเนื้อหาภายในไว้แล้วเรียกว่า Concrete method

using System;

public abstract class Pokemon{

    // Concrete method
    public void Pikachu(){
        Console.WriteLine("Pikachu");
    }

    // Abstract method
    public abstract void typeWater();
    
    // Abstract method
    public abstract void typeFire();
    
}

วิธีแยกว่าเมดธอดไหนเป็น Abstract method ดูได้จาก ตัวอย่างจะเห็นได้ว่า Method ที่มีการกำหนดเนื้อหาข้างในแล้วจะไม่ใช่ Abstract method และไม่มี keyword แบบที่กล่าวข้างต้น

Inheritance

คลาสที่สืบทอด Abstract class จะใช้ : หลังชื่อคลาสตามด้วยชื่อคลาสที่ต้องการจะสืบทอด คลาสที่สืบทอดจะต้องทำการ Override เมดธอดทั้งหมดที่เป็น Abstract method เข้ามาและกำหนดเนื้อหาคำสั่งที่ต้องการจะทำภายในเพิ่มในส่วนของเมดธอดที่เราจะทำการ Override จะมี keyword ว่า override หลังระดับการเข้าถึงของเมดธอด(Access Modifier)

class Trainer : Pokemon {

    public override void typeWater(){
        Console.WriteLine("Squirtle");
    }
    
    public override void typeFire(){
        Console.WriteLine("Charmander");
    }
    
}

การสืบทอดคลาสจากคลาสแม่สามารถทำได้หลายคลาสพร้อมกัน แต่ในภาษา C# คลาสที่สืบทอดสามารถสืบทอดคุณสมบัติได้จากคลาสเดียวเท่านั้น

Object class

การสร้างตัว Object เพื่อใช้เรียกใช้งานคลาสจะทำในส่วนของ Class main โดยการสร้าง Object เรียกใช้ Class ที่สืบทอดมาจาก Abstract class สามารถสร้างได้สองแบบ

class mainProgram{

    static void Main(string[] args){
        Pokemon Satoshi = new Trainer();    
            
        Satoshi.Pikachu();
        Satoshi.typeWater();
        Satoshi.typeFire();
    }
    
}

Output

Pikachu
Squirtle
Charmander

ถ้าสร้าง Object แบบนี้เป็นการ Polymorphism คือ การที่ใช้ตัวแปรชนิดคลาสแม่ (Pokemon) อ้างอิงถึง Object ของคลาสลูก (Trainer1) จะทำให้สามารถเรียกใช้งาน Method ที่สร้างใน Abstract class ที่ไม่ใช่ Abstract method ได้ จะเห็นว่าตอนเรียก Satoshi.Pikachu() แม้ว่าจะไม่มีเมดธอด Pikachu()อยู่ในคลาส Trainner1 ก็สามารถเรียกใช้เมดธอด Pikachu()ได้

using System;

// Abstract class
public abstract class Pokemon{

    // Concrete method
    public void Pikachu(){
        Console.WriteLine("Pikachu");
    }

    // Abstract method
    public abstract void typeWater();
    
    // Abstract method
    public abstract void typeFire();
    
}

class Trainer : Pokemon {

    public override void typeWater(){
        Console.WriteLine("Squirtle");
    }
    
    public override void typeFire(){
        Console.WriteLine("Charmander");
    }
    
}

class mainProgram{

    static void Main(string[] args){
        Pokemon Satoshi = new Trainer();    
        Satoshi.Pikachu();
        Satoshi.typeWater();
        Satoshi.typeFire();
    }
    
}

Output

Pikachu
Squirtle
Charmander

Abstract class ที่ทำงานร่วมกับ get กับ set

using System;

public abstract class Pokemon{

    // Abstract properties
    public abstract int Power{
        get;
        set;
    }
}

class Ivysaur : Pokemon {

    public int p;
    
    public override int Power{
        get{ return p; }
        set{ p = value; }   
    }
}

public class main{

    public static void Main(string[] args){  
      
        Ivysaur i = new Ivysaur();
        
        // Set
        i.Power = 9999;
        
        // Get
        Console.WriteLine(i.Power);
    }   
}

Output

9999

เปรียบเทียบการใช้ Abstract class กับภาษาอื่น

using System;

// Abstract class
public abstract class Pokemon{
    
    // Abstract properties
    public abstract int Power{ get; set; }

    // Abstract class
    public abstract void Type();

}
class Ivysaur : Pokemon {
    
    public int p;
    
    public Ivysaur(){
        Console.WriteLine("Ivysaur");
    }
    
    public override int Power{
        get{ return p; }
        set{ p = value; }   
    }
    
    public override void Type(){
        Console.WriteLine("Water");
    }
    
}


class mainProgram{ 
    
    static void Main(string[] args){
    
        Ivysaur i = new Ivysaur();
        
        // Setter
        i.Power = 9999; 
        
        // Getter
        Console.WriteLine(i.Power);
        
        i.Type();
    }
    
}

Output

Ivysaur
9999
Water

Java

โดยรวมแล้ว Java มี Syntax ที่คล้ายกับภาษา C# อยู่แล้วเลยทำให้โครงสร้างและรูปแบบการเขียนไม่ต่างกันมาก เปลี่ยนตรงคลาสที่มาสืบทอด Abstract class จะใช้ keyword ว่า extends แทน และเมดธอดที่ต้องการ Override จะไม่มี keyword ว่า abstract สามารถสร้างเป็นเมดธอดปกติที่ใช่ชื่อเหมือน Abstract method ที่เราต้อง Override ได้เลย

// Abstract class
abstract class Pokemon {

    // Abstract property
    public abstract int getPower();
    public abstract void setPower(int value);

    // Abstract method
    public abstract void Type();
}

class Ivysaur extends Pokemon {
    
    public int p;

    // Constructor
    public Ivysaur() {
        System.out.println("Ivysaur");
    }

    @Override
    public int getPower() {
        return p;
    }

    @Override
    public void setPower(int value) {
        this.p = value;
    }

    @Override
    public void Type() {
        System.out.println("Water");
    }
}

public class Main {

    public static void main(String[] args) {
    
        Ivysaur i = new Ivysaur();
        
        // Set Power
        i.setPower(9999);
        
        // Get Power
        System.out.println(i.getPower());
        
        i.Type();
        
    }
}

Output

Ivysaur
9999
Water

เนื่องจากภาษา Java ไม่ได้รองรับการทำงานแบบ Abstract property ทำให้ไม่สามารถใช้งานในรูปแบบ public abstract int Power { get; set; } เหมือนภาษา C# ได้ แต่เราสามารถกำหนดเมดธอด Getter กับ Setter ได้โดยสร้างเป็นเมดธอดปกติที่ทำงานเหมือนกันได้

C++

Abstract class in C++

ในภาษา C++ มีการสร้าง Abstract class คลาสเหมือนคลาสปกติทั่วไปแต่เมื่อมี Pure virtual method เพียงอันเดียวจะถือว่าคลาสนั้นเป็น Abstract class ทันที

Abstract method จะถูกเรียกว่า Pure virtual function ใน C++ และการกำหนดให้ = 0 เพื่อทำให้เป็น Pure virtual function เป็นการบังคับให้ไม่มีการ Implement เนื้อหาข้างในแต่ให้คลาสที่จะมาสืบทอดทำในส่วนนั้นแทน

#include <iostream>
using namespace std;

// Abstract class Pokemon
class Pokemon {

public:
    // Pure virtual function
    virtual void Type() = 0;
    
    virtual ~Pokemon() {}
};

Inheritance

จะใส่ : หลังชื่อคลาสตามด้วยชื่อ Abstract class ที่ต้องการจะสืบทอด เมดธอดที่ Override จาก Abstract class จะมี Keyword ว่า override หลังชื่อคลาส

class Ivysaur : public Pokemon {
    
public:{

    // Override
    void Type() override {
        cout << "Water" << endl;
    }
    
};

Abstract class ที่ทำงานร่วมกับ get กับ set

การทำงานของ Getter และ Setter จะทำงานเหมือนกับ Method ปกติที่มีการส่งค่าและเซ็ตค่า

class Pokemon {

public:

    // Pure virtual method
    virtual int getPower() const = 0;
    
    // Pure virtual method
    virtual void setPower(int power) = 0;
    
    virtual ~Pokemon() {}
};

class Ivysaur : public Pokemon {
    
public:

    int p;
    
    // Override
    int getPower() const override {
        return p;
    }
    
    // Override
    void setPower(int power) override {
        p = power;
    }
    
};

Python

Abstract class in Python

Python ต้องมีการ Import ตัว ABC และ abstractmethod มาเพื่อใช้ ในการสร้าง Abstract class จะใส่ ABC ที่ Import เข้ามาใส่ในวงเล็บหลังชื่อคลาสเพื่อกำหนดว่าเป็น Abstract class

และเมดธอดทุกอันที่ต้องการให้เป็น Abstract method เราจำเป็นที่ต้องใส่ @abstractmethod นำหน้าเมดธอดทุกครั้ง และภายในเมดธอดต้องใส่ pass เพื่อเป็นการไม่กำหนดเนื้อหาข้างในตัวเมดธอด

from abc import ABC, abstractm ethod

# Abstract class Pokemon
class Pokemon(ABC):
    
    # Abstract method
    @abstractmethod    
    def Type(self):
        pass

Inheritance

คลาสย่อยที่ต้องการสืบทอด Abstract class ต้องใส่ชื่อคลาสที่ต้องการสืบทอดลงในวงเล็บเพื่อบอกว่าเรากำลังสืบทอดคลาสอะไรอยู่ในตอนนี้ เมดธอดที่ Override จะสร้างเหมือนเมดธอดปกติ เพียงแต่เราจะใช้ชื่อที่เหมือนกับ Abstract method และ Implement ในส่วนของเนื้อหาข้างในขึ้นมา

class Ivysaur(Pokemon):

    def Type(self):
        print("Water")

Abstract class ที่ทำงานร่วมกับ get กับ set

ชื่อของ Getter และ Setter ต้องเหมือนกัน โดยถ้าเป็น Getter จะเพิ่ม @property แต่ถ้าเป็น Setter จะใส่ชื่อคลาสตามด้วย .setter ถ้าตามตัวอย่างจะใส่ @Power.setter

class Pokemon(ABC):

    @property
    @abstractmethod
    def Power(self):
        pass

    @Power.setter
    @abstractmethod
    def Power(self, value):
        pass
        
class Ivysaur(Pokemon):

    @property
    def Power(self):
        return self._p

    @Power.setter
    def Power(self, value):
        self._p = value
        

ในส่วนของคลาสที่มาสืบทอดก็ใส่เหมือนกันแต่ไม่ต้องใส่ @abstractmethod เหมือนกับใน Abstract class

reference :

  1. C++ Abstract Class and Pure Virtual Function : https://www.programiz.com/cpp-programming/pure-virtual-funtion

  2. abc — Abstract Base Classes : https://docs.python.org/3/library/abc.html

Last updated