
Entendendo a programação orientada a objetos (POO) em MQL5
Introdução
Neste artigo, compartilharemos um dos tópicos mais importantes da programação, que facilita a escrita de código, e nos ajuda a aplicar o princípio DRY (Do Not Repeat Yourself, não se repita) como desenvolvedores e programadores. Além disso, aumenta a segurança de qualquer software criado e fornece outras características. Falaremos sobre programação orientada a objetos (POO) e como podemos usar esse conceito ao trabalhar com o MQL5 (MetaQuotes Language).
Assim, abordaremos esse tópico interessante e importante através das seções a seguir:
O principal objetivo deste artigo é entender os fundamentos da programação orientada a objetos (POO) em geral e como ela pode ser útil na criação de software. A partir daí, aprenderemos como podemos aplicar essa abordagem em MQL5 para utilizar o que pode nos ajudar a criar software mais eficaz e seguro.
Se necessário, você pode encontrar recursos informativos sobre esse conceito, uma vez que ele é aplicável a outras linguagens de programação, como C++, Java, Python e outras. Toda a informação necessária sobre a linguagem MQL5 pode ser encontrada na documentação oficial.
O que é o POO?
Vamos começar com a definição de POO. A POO ajuda a criar e desenvolver software reutilizável sem duplicação de trabalho e código, aplicando o conceito DRY (don't repeat yourself, não se repita).
A POO nos ajuda a se aproximar da natureza do mundo, já que objetos nos cercam na vida cotidiana. Lidaremos com objetos e classes, onde objeto significa uma instância de uma classe e classe é um modelo para um objeto. Dentro do modelo, que é uma classe, detalhamos o comportamento do objeto.
Conceitos básicos de POO:
Ao usar POO no desenvolvimento, aplicam-se os seguintes princípios.
- Encapsulamento.
- Abstração.
- Herança.
- Polimorfismo.
1. Encapsulamento:
O encapsulamento é um método que permite vincular funções e dados em uma única classe, onde os dados e funções podem ser privados - acessíveis apenas dentro da classe - ou públicos - acessíveis fora da classe. O encapsulamento ajuda a ocultar a complexidade da implementação da classe e dá ao desenvolvedor controle total sobre seus dados, ajudando a rastrear todos os valores dependentes sem conflitos.
O encapsulamento ajuda a manter a funcionalidade de nosso sistema e evita muitos erros possíveis, além de fornecer um alto nível de controle ao desenvolvedor e simplificar testes e manipulação de dados de classes sem afetar ou alterar todo o código de software. Também ajuda a corrigir erros e simplifica o código.
O próximo diagrama descreve o conceito de encapsulamento:
2. Abstração:
A abstração é um método de ocultar detalhes não essenciais e apresentar apenas os detalhes essenciais. É um conceito mais amplo do que a encapsulação, mas ajuda a alcançar o mesmo objetivo: proteger dados e implementar funções sem o conhecimento completo do processo de implementação de todas as classes, apenas com uma compreensão do que precisa ser feito para que a implementação seja concluída.
Para atingir esse objetivo, precisamos incorporar dois métodos importantes - interface e implementação. A interface é um método que permite que as classes interajam entre si, enquanto a implementação é um método que contém todos os detalhes do código ou lógica das classes. Assim, a abstração ajuda a aumentar a segurança do software e permite evitar a repetição do processo de codificação do zero, desenvolvendo e codificando mais aplicativos com base nos já criados.
3. Herança:
Pelo nome, o conceito de herança significa que obtemos uma nova classe a partir de uma antiga, e a nova herda as funções da antiga. Nesse caso, a classe antiga é chamada de classe pai ou superclasse, e a nova classe derivada é chamada de classe filha. Esse conceito ajuda a aplicar o princípio DRY (não se repita), mantendo a capacidade de reutilização.
4. Polimorfismo:
O polimorfismo permite que funções processem dados de diferentes tipos. Por exemplo, podemos usar um método de soma para obter valores da soma (a) e (b) e outro para obter a soma (a), (b) e (c).
Em termos simples, o polimorfismo significa uma única interface e múltiplos métodos.
Resumindo, podemos dizer que a programação orientada a objetos (POO) é um modelo de programação que se concentra na organização do desenvolvimento de software usando objetos, que podem ter comportamentos e características únicos. Este é um modelo útil em programas grandes e complexos, especialmente se eles são atualizados com frequência.
Características da POO:
- Os programas que aplicam a POO incluem classes e funções.
- Há um alto nível de segurança de dados devido ao uso dos princípios de encapsulamento e abstração.
- Isso simplifica o trabalho em projetos complexos, pois o código pode ser dividido em pequenos blocos, o que pode reduzir a complexidade do projeto.
- Os processos de atualização e desenvolvimento tornam-se mais simples.
- A capacidade de reutilizar o código é alcançada por meio do princípio de herança.
- A capacidade de criar várias instâncias da mesma classe sem conflitos.
Existem muitas linguagens de programação que podem aplicar a abordagem da POO. As mais populares incluem C++, C#, Python, Java, JavaScript, PHP e outras. MQL5 também está incluída nessa lista.
POO em MQL5
Nesta seção, abordaremos a POO em MQL5 e aprenderemos como usá-la.
Antes de aplicar a POO em MQL5, precisamos entender como podemos usá-la no MQL5 da seguinte forma:
- Classes
- Modificador de acesso
- Construtores e destruidores
- Classes derivadas (filhas)
- Funções virtuais
- Objetos
Classes:
Em MQL5, quando precisamos criar uma classe que servirá como um modelo para um objeto, devemos declarar essa classe na área de visibilidade global da mesma forma que fazemos com funções. Podemos criar essa classe usando a palavra-chave "class", seguida de um identificador único desejado. Em seguida, dentro das chaves, podemos colocar nossas variáveis e métodos que são membros da classe. Após o segundo conjunto de chaves, colocamos um ponto e vírgula para finalizar a declaração da classe. Podemos usar essa declaração de classe em nosso programa ou em um arquivo incluído.
Aqui está um exemplo da declaração dessa classe:
class Cobject { int var1; // variable1 double var2; // variable1 void method1(); // Method or function1 };
Como podemos ver no exemplo anterior, temos três membros na classe: duas variáveis e um método ou função.
Modificadores de acesso:
Com esses modificadores de acesso, podemos definir quais variáveis e funções podemos usar fora da classe, e existem três palavras-chave de acesso: public, private e protected.
- Public: membros que podem estar disponíveis para uso fora da classe.
- Private: representa membros que não podem ser acessados para uso fora da classe, mas que só estão disponíveis para uso dentro da classe por meio de funções. A classe filha dessa classe não herdará esses membros privados.
- Protected: representa elementos que serão herdados por classes filhas, mas que são privados por natureza.
Aqui está um exemplo:
class Cobject { private: int var1; // variable1 protected: double var2; // variable1 public: void method1(); // Method or function1 };
Como podemos ver no exemplo anterior, temos três membros na classe com duas variáveis: uma é privada (private), outra é protegida (protected) e a terceira é pública (public).
Construtores e destruidores:
Se precisamos inicializar variáveis na classe, usamos um construtor. Se não o fornecermos, o compilador criará um por padrão, mas ele não será visível por padrão. O construtor também deve ser público. Um destrutor é uma função chamada automaticamente quando o objeto da classe é destruído. O destrutor tem o mesmo nome da classe, precedido pelo til (~). Independentemente de haver um destrutor ou não, strings, arrays dinâmicos e objetos requerem desalocação, então eles serão desalocados de qualquer maneira.
Abaixo está um exemplo de um construtor:
class CPrices { private: double open; // Open price double high; // High price double low; // Low price double close; // Close price public: //--- Default constructor CPrices(void); //--- Parametric constructor CPrices(double o,double h,double l, double c); };
Classes derivadas (filhas):
Como aprendemos anteriormente, o conceito de herança é uma das características mais valiosas e úteis da programação orientada a objetos (POO). Isso ocorre porque podemos criar uma classe filha de uma classe pai ou superclasse, e essa classe filha herda todos os membros da classe pai, exceto os privados. Depois disso, podemos adicionar novas variáveis e funções a essa classe filha.
Vejamos um exemplo: se tivermos uma classe pai para preços, podemos criar uma classe filha para preços diários, como mostrado abaixo:
class CDailyPrices : public CPrices { public: double open; // Open price double high; // High price double low; // Low price double close; // Close price };
Como podemos ver, o nome da classe pai é "CPrices" e "CDailyPrices" é a classe filha. Todos os membros públicos e protegidos de "CPrices" fazem parte da classe "CDailyPrices" e ainda são públicos.
Funções virtuais:
Se quisermos atualizar a forma como um método ou função funciona em uma classe filha, podemos fazer isso usando uma função (virtual) na classe pai e, em seguida, definir a função na classe filha. Por exemplo, se tivermos duas versões diferentes de uma função com base em uma classe. Para a classe pai, definimos a função usando a palavra-chave "virtual".
class CVar { public: virtual void varCal(); };
Em seguida, atualizamos a mesma função na classe filha.
class CVar1 : public CVar { public: int varCal(int x, int y); };
Objetos:
Os objetos têm um identificador único. Assim como ao criar uma variável, usaremos o nome da classe como o tipo antes do identificador do objeto. Podemos criar vários objetos pertencentes às nossas classes, pois só precisamos de um identificador único para cada um. Após declarar o objeto, podemos acessar qualquer membro público usando (.) - o ponto.
Vamos considerar um exemplo que mostra a criação de uma classe com uma variável inteira chamada "num_trades".
class CSystrades { public: int num_trades; };
Então, precisamos criar um objeto pertencente a esta classe, chamado "system1". Faremos isso seguindo estas etapas:
CSystrades system1;
Em seguida, podemos definir esse objeto com um valor (3):
system1.num_trades=3;
Exploramos como aplicar a programação orientada a objetos (POO) no MQL5, aprendendo alguns dos pontos mais importantes.
Exemplos de POOs
Nesta seção interessante, apresentaremos algumas aplicações simples da POO.
priceClass:
Neste aplicativo simples, precisamos verificar os preços em vários intervalos de tempo. Usamos três intervalos de tempo (diário, semanal e mensal). Também precisamos ver todos os preços (abertura, máxima, mínima, fechamento) em um só lugar, digamos, na guia "Experts". Após isso, podemos continuar a desenvolver programas mais complexos.
Em primeiro lugar, precisamos declarar uma classe seguindo estas etapas:
- Declare uma classe para os preços na área global e torne todos os membros comuns públicos usando a palavra-chave "class". Use a palavra-chave "public".
- Crie cinco variáveis (timeframe, open, high, low e close).
- Crie uma função "void" para exibir todos os dados de preços.
- Dentro da função OnInit, definiremos o seguinte para três timeframes:
class CPrices { public: string timeFrame; double open; double high; double low; double close; void pricesPrint() { Print(timeFrame," Prices = Open: ",open," - ","High: ",high,"-","Low: ",low,"-","Close: ",close); } };
Vamos criar objetos da classe para os preços diários, semanais e mensais.
CPrices CDailyPrices; CPrices CWeeklyPrices; CPrices CMonthlyPrices;
Dentro da função OnInit, definiremos o seguinte para os três intervalos de tempo:
- Uma string com o nome do timeframe.
- O preço de abertura usando a função iOpen.
- O preço máximo usando a função iHigh.
- O preço mínimo usando a função iLow.
- O preço de fechamento usando a função iClose.
- Chamaremos a função ou método "print".
int OnInit() { //--- Daily time frame CDailyPrices.timeFrame="Daily"; CDailyPrices.open=(iOpen(Symbol(),PERIOD_D1,1)); CDailyPrices.high=(iHigh(Symbol(),PERIOD_D1,1)); CDailyPrices.low=(iLow(Symbol(),PERIOD_D1,1)); CDailyPrices.close=(iClose(Symbol(),PERIOD_D1,1)); CDailyPrices.pricesPrint(); //--- Weekly time frame CWeeklyPrices.timeFrame="Weekly"; CWeeklyPrices.open=(iOpen(Symbol(),PERIOD_W1,1)); CWeeklyPrices.high=(iHigh(Symbol(),PERIOD_W1,1)); CWeeklyPrices.low=(iLow(Symbol(),PERIOD_W1,1)); CWeeklyPrices.close=(iClose(Symbol(),PERIOD_W1,1)); CWeeklyPrices.pricesPrint(); //--- Monthly time frame CMonthlyPrices.timeFrame="Monthly"; CMonthlyPrices.open=(iOpen(Symbol(),PERIOD_MN1,1)); CMonthlyPrices.high=(iHigh(Symbol(),PERIOD_MN1,1)); CMonthlyPrices.low=(iLow(Symbol(),PERIOD_MN1,1)); CMonthlyPrices.close=(iClose(Symbol(),PERIOD_MN1,1)); CMonthlyPrices.pricesPrint(); return(INIT_SUCCEEDED); }
Depois disso, podemos ver os preços após a execução do Expert Advisor na guia "Experts" da barra de ferramentas:
Aqui vemos três linhas:
- Na primeira linha, são exibidos os preços diários de abertura, máximo, mínimo e fechamento.
- Na segunda linha, são exibidos os mesmos preços, mas em dados semanais.
- Na terceira linha, são exibidos os mesmos preços, mas em dados mensais.
indicatorClass:
O programa deve exibir os valores de quatro tipos de médias móveis (simples, exponencial, suavizada e ponderada linearmente) usando POO. Aqui estão os passos simples para atingir esse objetivo:
Vamos declarar a classe do indicador CiMA usando a palavra-chave "class" e criar membros públicos para essa classe. São quatro variáveis públicas: MAType - para determinar o tipo de média móvel, MAArray - para determinar o array da média móvel, MAHandle - para determinar o handle de cada tipo, MAValue - para determinar o valor de cada média móvel. Também criaremos um método "void" ou uma função "valuePrint" e o corpo da função para exibir o valor de cada tipo de média móvel.
class CiMA { public: string MAType; double MAArray[]; int MAHandle; double MAValue; void valuePrint() { Print(MAType," Current Value: ",MAValue); }; };
Vamos criar os seguintes objetos para cada média móvel da classe:
- Nome da média móvel
- Handle da média móvel
- Array da média móvel
//--- SMA CiMA CSma; CiMA CSmaHandle; CiMA CSmaArray; //--- EMA CiMA CEma; CiMA CEmaHandle; CiMA CEmaArray; //--- SMMA CiMA CSmma; CiMA CSmmaHandle; CiMA CSmmaArray; //--- LWMA CiMA CLwma; CiMA CLwmaHandle; CiMA CLwmaArray;
Para cada tipo de média móvel, realizaremos as seguintes etapas dentro da função OnInit:
- Definiremos o nome da média móvel.
- Definiremos o handle da média móvel.
- Configuraremos o sinalizador AS_SERIES para o array usando ArraySetAsSeries.
- Obteremos os dados do buffer da média móvel usando a função CopyBuffer.
- Definiremos o valor da média móvel e o normalizaremos usando a função NormalizeDouble.
- Chamaremos o método ou função "Print".
int OnInit() { //--- SMA CSma.MAType="Simple MA"; CSmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_SMA,PRICE_CLOSE); ArraySetAsSeries(CSmaArray.MAArray,true); CopyBuffer(CSmaHandle.MAHandle,0,0,3,CSmaArray.MAArray); CSma.MAValue=NormalizeDouble(CSmaArray.MAArray[1],_Digits); CSma.valuePrint(); //--- EMA CEma.MAType="Exponential MA"; CEmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_EMA,PRICE_CLOSE); ArraySetAsSeries(CEmaArray.MAArray,true); CopyBuffer(CEmaHandle.MAHandle,0,0,3,CEmaArray.MAArray); CEma.MAValue=NormalizeDouble(CEmaArray.MAArray[1],_Digits); CEma.valuePrint(); //--- SMMA CSmma.MAType="Smoothed MA"; CSmmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_SMMA,PRICE_CLOSE); ArraySetAsSeries(CSmmaArray.MAArray,true); CopyBuffer(CSmmaHandle.MAHandle,0,0,3,CSmmaArray.MAArray); CSmma.MAValue=NormalizeDouble(CSmmaArray.MAArray[1],_Digits); CSmma.valuePrint(); //--- LWMA CLwma.MAType="Linear-weighted MA"; CLwmaHandle.MAHandle=iMA(_Symbol,PERIOD_CURRENT,10,0,MODE_LWMA,PRICE_CLOSE); ArraySetAsSeries(CLwmaArray.MAArray,true); CopyBuffer(CLwmaHandle.MAHandle,0,0,3,CLwmaArray.MAArray); CLwma.MAValue=NormalizeDouble(CLwmaArray.MAArray[1],_Digits); CLwma.valuePrint(); return(INIT_SUCCEEDED); }
Após compilar e executar o código, veremos quatro linhas para cada tipo de média móvel. Cada linha exibirá o valor da média móvel:
Como mencionado anteriormente, esses aplicativos podem ser aprimorados para realizar tarefas mais complexas. No entanto, nosso objetivo neste artigo é aprender os fundamentos da programação orientada a objetos (POO) e aplicá-los na prática.
Considerações finais
Neste artigo, exploramos os fundamentos de uma abordagem muito importante na programação. A programação orientada a objetos (POO) ajuda na criação de software seguro, simplificando o desenvolvimento ao dividir o código em pequenos blocos. Isso permite criar várias instâncias da mesma classe sem conflitos, mesmo que elas se comportem de maneira diferente, proporcionando maior flexibilidade e segurança nas atualizações.
Aprendemos também como aplicar essa abordagem importante no MQL5 para obter todas essas incríveis possibilidades. Em seguida, exploramos alguns aplicativos simples que podem ser criados aplicando a POO no MQL5.
Espero que o artigo tenha sido útil.
Se você deseja aprender mais sobre a criação de sistemas de negociação em MQL5 com base nos indicadores mais populares, bem como o desenvolvimento e aplicação de indicadores personalizados em Expert Advisors, você pode conferir meus outros artigos. Você pode encontrar a lista completa de artigos em meu perfil.
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/12813





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso