iT邦幫忙

2023 iThome 鐵人賽

DAY 13
0
SideProject30

從零開始的外匯自動程式交易系列 第 13

DAY13 物件導向程式設計

  • 分享至 

  • xImage
  •  

物件導向程式設計(Object-oriented programming,OOP)

MQL5相較於MQL4最大的更新便是增加了物件導向,而OOP(Object-oriented programming)可以讓我們避免做不必要的執行,使運用更加簡潔與靈活。
很多人(包括我)都曾被這個新的概念迷惑,會覺得他很抽象,但在了解基本知識後,他就變得恨和藹可親了。所以今天我就從一個新手的角度來分享物件導向是什麼,還有他在MQL5中應用的時機。

類(classes)與物件(Object)

OOP的基礎建立在classes和objects上,class為創建object的範本。用實際生活舉例:假設object為一台手機,而每台手機會有唯一獨自的imei碼,而class便是製作手機的設計圖,包含內存、電池容量、鏡頭畫素等狀態與功能,廠商可以用同個class生產更多object,object變數便是用來區分不同的手機。

存取修飾詞(Access Modifiers)

存取修飾詞(Access Modifiers)是用於控制類別成員(屬性和方法)可見性和訪問權限的關鍵字。它們確定了哪些部分的程式碼可以訪問類別的成員,並以何種方式訪問這些成員。以下是他的修飾詞:

  • public:這是最開放的存取修飾詞,表示成員可以被任何程式碼訪問。在類別的外部和內部都可以訪問。例如,一個公共方法可以在任何地方調用。

  • private:私有成員僅限於同一個類別內部訪問。這意味著外部程式碼無法直接訪問私有屬性或方法。私有成員通常用於實現封裝和隱藏內部實現細節。

  • protected:受保護成員可以在同一個類別內部訪問,以及在其子類別中訪問。這是實現繼承和多態性的重要概念。外部程式碼無法直接訪問受保護成員。

  • package-private(Java特有):這種存取修飾詞允許成員在同一個包(package)中訪問,但在包之外無法訪問。它通常在Java中使用。

  • internal(C#特有):這是C#中的一種存取修飾詞,允許成員在同一個組件(assembly)內部訪問,但在不同組件中無法訪問。它有助於實現模組化和封裝。

  • default(MQL5特有):如果未指定存取修飾詞,則默認為 default,表示成員可以在同一個文件中訪問,但在不同文件中無法訪問。

建構函式(Constructors)

建構函式(Constructors)是物件導向程式設計中的特殊方法,它們用於初始化類別的新物件。創建一個新的物件時,建構函式會自動調用,以確保物件在被使用之前處於一個合適的狀態。如果沒有明確定義構造函數,則會自動創建一個預設函數來初始化變數。以下是他的特點:

  • 名稱與類別相同:建構函式的名稱必須與其所屬的類別完全相同。

  • 沒有返回值:建構函式通常沒有返回值,包括不返回 void。它們的主要職責是初始化物件,不需要返回任何東西。

  • 可以有參數:建構函式可以具有參數,以便在初始化過程中接受外部提供的信息。可以根據需要對物件進行不同的初始化。

  • 多個建構函式(方法重載):同一個類別可以擁有多個建構函式,每個建構函式可以接受不同數量和類型的參數。這被稱為方法重載(Method Overloading)。

  • 初始化成員變數:建構函式通常用於設置物件的成員變數,以確保它們具有合適的初始值。

範例

class MyClass {
private:
    int myData;

public:
    // 建構函式,無參數
    MyClass() {
        myData = 0; // 初始化成員變數
        Print("Constructor called without parameters.");
    }

    // 建構函式,帶參數
    MyClass(int initData) {
        myData = initData; // 使用參數初始化成員變數
        Print("Constructor called with parameter: ", initData);
    }

    // 成員函式,用於顯示成員變數的值
    void DisplayData() {
        Print("My Data: ", myData);
    }
};

int OnInit() {
    MyClass obj1;         // 使用無參數建構函式
    MyClass obj2(42);     // 使用帶參數建構函式

    obj1.DisplayData();   // 顯示 obj1 的成員變數
    obj2.DisplayData();   // 顯示 obj2 的成員變數

    return(INIT_SUCCEEDED);
}

//輸出:Constructor called without parameters.
//Constructor called with parameter: 42
//My Data: 0
//My Data: 42

衍生類(Derived Classes)

衍生類(Derived Classes)是物件導向程式設計中的一個概念,它指的是基於一個現有的類別(稱為基類或父類)創建一個新的類別。衍生類繼承了基類的特性,包括屬性和方法,同時可以添加新的特性或修改繼承的特性。這種概念是實現繼承的基礎,建立一個階層結構的類別。以下是一些關於衍生類的重要概念:

  • 基類(Base Class)或父類(Parent Class):基類是衍生類的原型,它包含了共享的特性和方法。基類通常是一個通用的類別,可以用來創建多個不同的衍生類。

  • 衍生類(Derived Class)或子類(Sub Class):衍生類是基於基類創建的新類別。它可以繼承基類的成員,同時可以添加自己的成員,或者修改繼承的成員。

  • 繼承(Inheritance):繼承是指一個衍生類可以繼承基類的屬性和方法。這使得可以在不從頭開始編寫代碼的情況下,重用和擴展現有的類別。

  • 覆寫(Override):當衍生類需要修改基類中的方法時,可以使用方法覆寫。覆寫允許衍生類提供自己的版本,以取代基類的方法實現。

範例:

//創建parent class

class CFruit {
protected:
    string name;

public:
    // 建構函式
    CFruit(string _name) {
        name = _name;
    }

    // 方法
    void Describe() {
        Print("This is a ", name);
    }
};

//創建sub class

class CApple : public CFruit {     //子類:父類
public:
    // 建構函式
    CApple() : CFruit("Apple") {}
};

//使用

void OnStart() {
    CApple apple;
    
    apple.Describe(); // 輸出:This is a Apple
}

基類 CFruit 定義了通用的水果特性,而衍生類 CApple 繼承了這些特性並添加了自己的水果名稱。

虛函數(Virtual Functions)

虛函數(Virtual Functions)是物件導向程式設計中的一個重要概念,用於實現多態性(Polymorphism)。虛函數允許不同的類別在繼承層次結構中具有相同的函數名稱,但具體實現可以根據每個子類別的需要而不同。以下是虛函數的一些特點:

  • 定義:虛函數在基類(父類)中被聲明,使用 virtual 關鍵字。

  • 覆寫:衍生類(子類)可以覆寫基類中的虛函數,以提供自己的實現。覆寫使用 override 關鍵字(在C++中,MQL5亦同)或相應的語法(在其他語言中)來標記。

  • 多態性(Polymorphism):虛函數實現多態性,這意味著通過基類指針或參考調用虛函數時,將執行實際對象的版本,而不僅僅是基類的版本。這使在處理不同的對象時,可以不必關心它們的實際類型。

  • 運行時綁定:虛函數的實際實現是在運行時決定的,而不是在編譯時。這種動態決定使我們可以根據對象的實際類型調用正確的函數版本。

成果展示

以上便是物件導向程式設計的大致概念了,接下來就由剛剛舉例的手機為實例,編寫一段包含以上概念的範例供大家參考(編寫語言:MQL5)

// 父類 - 手機
class CPhone {
protected:
    string imei; // 唯一的IMEI碼
    int memory;  // 內存容量(GB)
    int battery; // 電池容量(mAh)

public:
    // 建構函式
    CPhone(string _imei, int _memory, int _battery) {
        imei = _imei;
        memory = _memory;
        battery = _battery;
    }

    // 虛函數 - 顯示手機資訊
    virtual void ShowInfo() {
        Print("IMEI: ", imei);
        Print("Memory: ", memory, " GB");
        Print("Battery: ", battery, " mAh");
    }
};

// 衍生類 1 - Android手機
class CAndroidPhone : public CPhone {
private:
    int cameraResolution; // 鏡頭畫素

public:
    // 建構函式
    CAndroidPhone(string _imei, int _memory, int _battery, int _cameraResolution)
        : CPhone(_imei, _memory, _battery) {
        cameraResolution = _cameraResolution;
    }

    // 覆寫虛函數 - 顯示手機資訊
    void ShowInfo() override {
        Print("Android Phone Info:");
        CPhone::ShowInfo(); // 調用父類的虛函數
        Print("Camera Resolution: ", cameraResolution, " MP");
    }
};

// 衍生類 2 - iPhone手機
class CiPhone : public CPhone {
private:
    string faceID; // Face ID功能

public:
    // 建構函式
    CiPhone(string _imei, int _memory, int _battery, string _faceID)
        : CPhone(_imei, _memory, _battery) {
        faceID = _faceID;
    }

    // 覆寫虛函數 - 顯示手機資訊
    void ShowInfo() override {
        Print("iPhone Info:");
        CPhone::ShowInfo(); // 調用父類的虛函數
        Print("Face ID: ", faceID);
    }
};

// 在OnStart函式中測試手機類別
void OnStart() {
    CAndroidPhone androidPhone("123456789", 64, 3000, 12);
    CiPhone iPhone("987654321", 128, 2800, "TrueDepth");

    CPhone* phones[] = {&androidPhone, &iPhone};

    for (int i = 0; i < ArraySize(phones); i++) {
        phones[i].ShowInfo(); // 使用虛函數顯示手機資訊
        Print("==========");
    }
}

輸出為:

Android Phone Info:
IMEI: 123456789
Memory: 64 GB
Battery: 3000 mAh
Camera Resolution: 12 MP
==========
iPhone Info:
IMEI: 987654321
Memory: 128 GB
Battery: 2800 mAh
Face ID: TrueDepth
==========

範例中我們創建了一個父類 CPhone 代表手機,它包括IMEI碼、內存、電池容量等屬性。然後創建了兩個衍生類 CAndroidPhone 和 CiPhone,分別代表Android手機和iPhone手機。每個衍生類都有自己的屬性,並覆寫了父類中的 ShowInfo 虛函數以顯示手機資訊。

最後 OnStart 函式中,我們創建了兩個手機物件並使用虛函數 ShowInfo 來顯示它們的資訊。

以上便是OOP的概念統整,因為本人也才剛學完不久,若有那裡錯誤請留言讓我知道,我會盡快改正


上一篇
DAY12 函數定義及運用
下一篇
DAY14 中秋節快樂,簡單說一下未來規劃
系列文
從零開始的外匯自動程式交易30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言