O POE para crianças em idade escolar.

 

========================================================================================================================

Este tópico conterá alguns exemplos simples de como usar o OOP.

Perguntas de programadores novatos são bem-vindas. Aqueles que realmente querem entender o OOP.

"Caras espertos" que acham que estou fazendo algo errado, comecem seus próprios fios e façam isso bem ali. Ninguém precisa de você aqui.

As disputas sobre a necessidade e inutilidade do OOP também são irrelevantes aqui.

========================================================================================================================


1 Suponha que estejamos fazendo algo com pontos no plano coordenado.

Suponha que haja apenas 10 deles.

Há várias maneiras de armazená-las na memória.

Assim:

double x1, y1, x2, y2, x3, y3, x4, y4, x5, y5, x6, y6, x7, y7, x8, y8, x9, y9, x10, y10;

Ou assim:

double pointsX[10];
double pointsY[10];

Ou assim:

double points[10][2];

Mas é muito mais conveniente fazê-lo desta maneira:

struct POINT
{
  double x;
  double y;
};

POINT points[10];

Temos um novo tipo de dados, que é um ponto em um avião.

Trabalhamos com um ponto como uma entidade separada.

Como exemplo, nós escrevemos uma função que calcula a distância entre os pontos.

POINT p1, p2;

double D = Distance( p1, p2 );

double Distance( const POINT& p1, const POINT& p2 )
{
  double dx = p1.x - p2.x;
  double dy = p1.y - p2.y;
  return sqrt( dx * dx + dy * dy );
}

Desta forma, o OOP nos dá a capacidade de programar em uma linguagem de tarefa.


Nós continuamos...

 

2. Polimorfismo.

Suponha que tenhamos este código:

int iA = 1;
int iB = 3;

double dA = 4.5;
double dB = 3.14;

string sA = "abcd";
string sB = "efgh";

int iC = iA + iB;

double dC = dA + dB;

string sC = sA + sB;

Nesses três casos, há três funções de adição diferentes por trás do sinal de mais.

Isto é chamado de polimorfismo.

O OOP nos permite estender esta ação a outros dados.

Por exemplo, temos uma classe matricial. Ele está localizado no arquivo matrix.mqh

Então, podemos escrever este código:

#include <matrix.mqh>

matrix< double > mA( 2, 2 );
mA[0][0] = 1.0;
mA[0][1] = 2.0;
mA[1][0] = 3.0;
mA[1][1] = 4.0;

matrix< double > mB( 2, 2 );
mB[0][0] = 5.0;
mB[0][1] = 6.0;
mB[1][0] = 7.0;
mB[1][1] = 8.0;

matrix< double > mC = mA + mB;

Aqui o OOP nos permite dividir a responsabilidade entre as diferentes partes do programa.

Quando escrevemos uma classe matricial, não pensamos como ela será usada.

Mas quando é escrito e depurado, nós o usamos em várias tarefas sem pensar nas regras de adição e multiplicação de matrizes.

Acabamos de colocar + e *.


A continuar ...

 

3. Funções virtuais.

Suponha que tenhamos escrito várias classes representando formas geométricas.

Todos eles herdam de uma classe base Forma.

class Shape
{
public:
  Shape();

  virtual void Draw() = 0;
};

class Circle : public Shape
{
public:
  Circle();

  virtual void Draw();
};

class Rectangle : public Shape
{
public:
  Rectangle();

  virtual void Draw();
};

class Star : public Shape
{
public:
  Star();

  virtual void Draw();
};

Podemos colocar todas estas formas em uma só matriz se declararmos uma matriz de ponteiros para a classe base.

Shape* shapes[10];

Na função Init() nós preenchemos esta matriz.

void Init()
{
  for( int i = 0; i < 10; i++ )
  {
    switch( i % 3 ){
      case 0:
        shapes[i] = new Circle();
        break;
      case 1:
        shapes[i] = new Rectangle();
        break;
      case 2:
        shapes[i] = new Star();
        break;
    }
  }
}

A função OnPaint() é chamada quando precisamos exibir todas as formas.

void OnPaint()
{
   for( int i = 0; i < 10; i++ )
   {
      shapes[i].Draw();
   }
}

Nós fazemos loops em todos os formatos e chamamos a função Draw() para cada um deles.

Para cada forma chamamos de sua própria função que sabe desenhar essa forma particular.

Esta é a essência das funções virtuais.

E, é claro, não se esqueça de apagá-los no final.

void OnDeinit()
{
  for( int i = 0; i < 10; i++ ){
    delete shapes[i];
  }
}


Para continuar ...

 

Não, eles (o menino da escola) não entenderiam. Especialmente não algum tipo de matriz. Eles dirão: por que precisamos deste polimorfismo... algum tipo de polimorfismo? Mais ainda, que no emculus sua eficiência só é aparente se houver pelo menos 10 variantes. pelo menos 10 variantes.

Provavelmente, deveríamos começar com a possibilidade de combinar funções e variáveis - para nos livrarmos das variáveis globais e da confusão associada a elas.

 
Dmitry Fedoseev:

Não, eles (o menino da escola) não entenderiam. Especialmente não algum tipo de matriz. Eles dirão: por que precisamos deste polimorfismo... algum tipo de polimorfismo? Mais ainda, que no emculus sua eficiência só é aparente se houver pelo menos 10 variantes. pelo menos 10 variantes.

Talvez devêssemos começar com a possibilidade de combinar funções e variáveis - para nos livrarmos das variáveis globais e da confusão associada a elas.

Acho que ))))

Pessoalmente, ainda não entendo se este OOP é necessário ou não. Não vejo nenhuma vantagem óbvia (a menos que você esteja fazendo o mesmo tipo de tarefas, eu acho). E não encontrei uma introdução simples e clara a este tópico (talvez porque eu não estivesse realmente procurando por ele?) )))))))

 

4. Encapsulamento.

Pode-se ouvir com freqüência aqui: "Por que precisamos fazer membros de classe enterrados no OOP? Queremos que tudo esteja aberto e acessível em todos os lugares".

Mas o OOP não obriga a fazer fechar todos os membros. Cabe ao programador decidir o que deve ser escondido e o que não deve.

E geralmente eles escondem as coisas que devem ser escondidas para reduzir a probabilidade de corrupção acidental de dados.

Temos, por exemplo, um botão, que pode ser ajustado para qualquer cor.

class ColorButton
{
   color myColor;

public:
   ColorButton( color clr ) : myColor( clr ){}

   color GetColor() const
   {
      return myColor;
   }

   void SetColor( color clr )
   {
      myColor = clr;
      Update();
   }

   void Update();
};

Poderíamos fazer a variável myColor aberta e mudar a cor do botão a qualquer momento através de uma simples atribuição.

Mas a atribuição desta variável não fará com que o botão seja redesenhado imediatamente.

Portanto, tornamos a variável myColor privada. E para mudar a cor, chamamos a função SetColor().

Esta função, além de atribuir uma variável, diz ao sistema que o botão deve ser pintado de novo.

Nesta função, você pode colocar quaisquer outras ações necessárias.

A função GetColor() pode ser usada para obter a cor do botão. Sua chamada não é mais cara do que uma referência direta à variável,

porque o compilador pode facilmente otimizar isto.

 
Koldun Zloy:

4. Encapsulamento.


Estou correto ao assumir que, neste exemplo, trata-se, em gíria, dos próprios heteros e setores?

 
Roman:

Estou correto ao assumir que neste exemplo são, em gírias, os próprios heters e setors?

Sim. Isso é correto.

 
Não há getters e setters no emculus.
 
Dmitry Fedoseev:
Não há getters e setters no emcool.

Isto não é determinado pela MQL, mas pelo programador. Se ele quiser, eles o farão.

 
Ihor Herasko:

Isto não é determinado pela MQL, mas pelo programador. Se ele quiser, eles o farão.

A linguagem de programação determina isso.