//+------------------------------------------------------------------+ //| CTradeSignal.mqh | //| Copyright 2025, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "SoloTrade Official, Solomon" #property link "https://www.mql5.com/en/users/SoloTradeOfficial" #property version "1.00" #property description "THE WORLD MOST INTELLIGENT FOREX AI/ALGO BOTS EVER IN" "HUMAN HISTORY OF FINTECH, BY SOLOMON ESHUN" "\nTrading Bots in MQL5" // Scope Resolution Operator `::` // --- DECLARATION --- // This part is like the public menu. It tells us WHAT the class can do. class CTradeSignal { private: string m_symbol; int m_magic_number; public: // Constructor declaration CTradeSignal(string symbol, int magic_number); // Method declaration void CheckSignal(); }; // --- DEFINITION / IMPLEMENTATION --- // This part is the kitchen. It's HOW the work gets done. // Because this code is outside the class { } block, we MUST use :: // Definition for the constructor CTradeSignal::CTradeSignal(string symbol, int magic_number) { m_symbol = symbol; m_magic_number = magic_number; Print("Trade Signal object created for ", m_symbol); } // Definition for the CheckSignal method void CTradeSignal::CheckSignal() { // Some complex logic to check for a trade signal... Print("Checking for a signal on ", m_symbol, " with magic number ", m_magic_number); } //+------------------------------------------------------------------+ // NOTES BELOW //You are asking fantastic questions that get to the heart of Object-Oriented Programming (OOP) design. Let's break down both of these concepts. // //--- // //### Part 1: The Scope Resolution Operator (`::`) // //This is a syntax tool, a way of giving the compiler an exact address for a piece of code. // //**The Core Idea:** The `::` operator tells the compiler, "The function I am defining on the left of the `::` belongs to the class I am naming on the right." It resolves the *scope* of the function. // //**Analogy: The Office Building** // //Imagine you have a large office building (your entire program). The building has several departments: Sales, Marketing, and Engineering (these are your classes). // //Each department has a manager named "John." // //* `Sales::John` //* `Marketing::John` //* `Engineering::John` // //If you just shout "John!", nobody knows who you're talking about. You need to be specific. The `::` is how you specify which "department" (class) the "person" (function) belongs to. // //So, `Car::Car(...)` means "I am defining the `Car` constructor that belongs to the `Car` class." // //#### Why Do We Need This? // //The main reason is for **code organization**. It's considered very good practice to separate a class's *declaration* from its *definition (or implementation)*. // //1. **The Declaration (The "What"):** This goes in a header file (e.g., `Car.mqh`). It's like the table of contents for your class. It tells the world what the class is named and what public functions it has, but not *how* they work. // //2. **The Definition (The "How"):** This can go in the same file (usually below the declaration) or a separate `.cpp` file in larger projects. This is where you write the actual code for each function. Because this code is now *outside* the `class { ... }` block, you must use the scope resolution operator (`::`) to tell the compiler which class each function belongs to. // //#### MQL5 Example: // //Let's see this in action with a `CTradeSignal` class. // //**File: `CTradeSignal.mqh`** // //```mql5 //// --- DECLARATION --- //// This part is like the public menu. It tells us WHAT the class can do. // //class CTradeSignal //{ //private: // string m_symbol; // int m_magic_number; // //public: // // Constructor declaration // CTradeSignal(string symbol, int magic_number); // // // Method declaration // void CheckSignal(); //}; // // //// --- DEFINITION / IMPLEMENTATION --- //// This part is the kitchen. It's HOW the work gets done. //// Because this code is outside the class { } block, we MUST use :: // //// Definition for the constructor //CTradeSignal::CTradeSignal(string symbol, int magic_number) //{ // m_symbol = symbol; // m_magic_number = magic_number; // Print("Trade Signal object created for ", m_symbol); //} // //// Definition for the CheckSignal method //void CTradeSignal::CheckSignal() //{ // // Some complex logic to check for a trade signal... // Print("Checking for a signal on ", m_symbol, " with magic number ", m_magic_number); //} //``` // //By separating the "what" from the "how," your class declaration at the top becomes very clean and easy to read, while the complex logic is neatly organized below. // //--- // //### Part 2: Composition ("Has-A" Relationship) // //This is a powerful design pattern. You've already learned about Inheritance, which creates an "Is-A" relationship (`A CMACrossoverSignal` **is a** `CSignal`). // //**Composition creates a "Has-A" relationship.** // //**The Core Idea:** Instead of a class inheriting features, it is *composed* of other objects. It holds other objects inside it as member variables. // //**Analogy: The Car (Again!)** // //A `Car` is a perfect example of composition. // //* A `Car` **is not** an `Engine`. //* A `Car` **is not** a `Wheel`. //* Instead, a `Car` **has an** `Engine`. //* A `Car` **has** four `Wheels`. //* A `Car` **has a** `Transmission`. // //The `Car` class coordinates the work of all its component parts. When you press the accelerator in the `Car`, the `Car` object tells its `Engine` object to increase RPMs, which in turn tells the `Transmission` object to engage a gear, which tells the `Wheel` objects to turn. // //#### MQL5 Example: An Expert Advisor Composed of Parts // //Let's model an EA. An EA might be composed of a signal generator, a risk manager, and a trade executor. // //**Step 1: Define the "Part" Classes** // //We'll use the `CRiskManager` from our Abstraction example and a simplified `CTradeExecutor`. // //```mql5 //// (Assuming CRiskManager class is defined as in the previous example) // //class CTradeExecutor //{ //public: // void ExecuteBuy(string symbol, double lots) // { // Print("EXECUTOR: Placing BUY order for ", lots, " lots on ", symbol); // // Real MQL5 OrderSend() logic would go here // } //}; //``` // //**Step 2: Define the "Whole" Class using Composition** // //The `CExpertAdvisor` class will *contain* objects of the other classes as member variables. // //```mql5 //// Include the files for the parts //#include "CRiskManager.mqh" //#include "CTradeExecutor.mqh" //// (Assuming CTradeSignal from above is also available) // //class CExpertAdvisor //{ //private: // // --- COMPOSITION HAPPENS HERE --- // // The EA "has-a" signal, a risk manager, and an executor. // CTradeSignal m_signal; // CRiskManager m_risk_manager; // CTradeExecutor m_trade_executor; // //public: // // The EA's constructor initializes its component parts // CExpertAdvisor(string symbol, int magic_number) : m_signal(symbol, magic_number), // m_risk_manager(1.0, 5), // 1% risk, 5 trades max // m_trade_executor() // { // Print("Expert Advisor object created and ready."); // } // // // The EA's main logic function // void OnTick() // { // // The EA delegates work to its parts. // // 1. It asks its signal component for a signal. // // m_signal.CheckSignal(); // Pretend this returns a trade direction // // ENUM_TRADE_DIRECTION tradeDirection = GetSignalFromSomewhere(); // Fake signal // // if (tradeDirection != TRADE_DIRECTION_NONE) // { // // 2. It asks its risk manager component if a trade is allowed. // if (m_risk_manager.isTradeAllowed(30.0)) // 30 pips SL // { // // 3. If everything is OK, it tells its trade executor to place the trade. // m_trade_executor.ExecuteBuy(_Symbol, 0.1); // } // } // } // // // Fake function for demonstration // ENUM_TRADE_DIRECTION GetSignalFromSomewhere() { return TRADE_DIRECTION_BUY; } //};``` // //**Step 3: Using the Composed Object** // //```mql5 //// In your main .mq5 file // //#include "CExpertAdvisor.mqh" // //// Create the main EA object //CExpertAdvisor MyEA("EURUSD", 12345); // //// The main OnTick function simply delegates all work to our EA object. //void OnTick() //{ // MyEA.OnTick(); //} //``` // //### Summary: Composition vs. Inheritance // //| Feature | Inheritance ("Is-A") | Composition ("Has-A") | //| :--- | :--- | :--- | //| **Relationship** | A derived class is a specialized version of its base class. | An object is built from other, independent objects. | //| **Flexibility** | Static. The relationship is fixed when you compile the code. | Highly flexible. You can often change the "parts" at runtime. | //| **Coupling** | Tightly coupled. A change in the base class can break all derived classes. | Loosely coupled. The "whole" only cares about the public interface of its "parts". | //| **When to Use** | When you can say "Type B is a type of Type A". (A `Toyota` is a `Car`). | When you can say "Type A has a Type B". (A `Car` has an `Engine`). | // //Generally, modern programming advice is to **"prefer composition over inheritance."** It leads to more flexible, scalable, and maintainable code, just like you saw with the `CExpertAdvisor` example.