El EOP para escolares.

 

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

Este tema contendrá algunos ejemplos muy sencillos de cómo utilizar la POO.

Las preguntas de los programadores novatos son bienvenidas. Aquellos que realmente quieren entender la OOP.

"Los listillos" que creen que estoy haciendo algo mal, inicien sus propios hilos y háganlo allí mismo. Nadie te necesita aquí.

Las discusiones sobre la necesidad y la inutilidad de la OOP también son irrelevantes aquí.

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


1 Supongamos que estamos haciendo algo con puntos en el plano de coordenadas.

Supongamos que sólo hay 10.

Hay varias formas de almacenarlas en la memoria.

Así:

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

O así:

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

O así:

double points[10][2];

Pero es mucho más cómodo hacerlo así:

struct POINT
{
  double x;
  double y;
};

POINT points[10];

Tenemos un nuevo tipo de datos, que es un punto en un plano.

Trabajamos con un punto como entidad independiente.

Como ejemplo, escribimos una función que calcula la distancia entre puntos.

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 );
}

De este modo, la POO nos da la posibilidad de programar en un lenguaje de tareas.


Seguimos...

 

2. Polimorfismo.

Supongamos que tenemos 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;

En estos tres casos, hay tres funciones de adición diferentes detrás del signo más.

Esto se llama polimorfismo.

La POO nos permite ampliar esta acción a otros datos.

Por ejemplo, tenemos una clase matriz. Se encuentra en el archivo matrix.mqh

Entonces podemos escribir 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;

Aquí la POO nos permite dividir la responsabilidad entre diferentes partes del programa.

Cuando escribimos una clase matriz, no pensamos en cómo se va a utilizar.

Pero cuando está escrito y depurado, lo utilizamos en diversas tareas sin pensar en las reglas de la suma y la multiplicación de matrices.

Sólo ponemos + y *.


Continuará...

 

3. Funciones virtuales.

Supongamos que hemos escrito varias clases que representan formas geométricas.

Todas ellas heredan de una clase base Shape.

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 poner todas estas formas en un array si declaramos un array de punteros a la clase base.

Shape* shapes[10];

En la función Init() llenamos este array.

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;
    }
  }
}

La función OnPaint() es llamada cuando necesitamos mostrar todas las formas.

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

Hacemos un bucle a través de todas las formas y llamamos a la función Draw() para cada una de ellas.

Para cada forma llamamos a su propia función que sabe cómo dibujar esa forma en particular.

Esta es la esencia de las funciones virtuales.

Y, por supuesto, no te olvides de borrarlos al final.

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


Para continuar...

 

No, ellos (el escolar) no lo entenderían. Especialmente no una especie de matriz. Dirán: ¿por qué necesitamos este polimorfismo... ¿algún tipo de polimorfismo? Más aún, que en el émulo su eficacia es evidente sólo si hay al menos 10 variantes. al menos 10 variantes.

Probablemente, deberíamos empezar con la posibilidad de combinar funciones y variables - para deshacernos de las variables globales y la confusión asociada a ellas.

 
Dmitry Fedoseev:

No, ellos (el escolar) no lo entenderían. Especialmente no una especie de matriz. Dirán: ¿por qué necesitamos este polimorfismo... ¿algún tipo de polimorfismo? Más aún, que en el émulo su eficacia es evidente sólo si hay al menos 10 variantes. al menos 10 variantes.

Tal vez deberíamos empezar con la posibilidad de combinar funciones y variables, para deshacernos de las variables globales y la confusión asociada a ellas.

Supongo que ))))

Personalmente, sigo sin entender si esta OOP es necesaria o no. No veo ninguna ventaja evidente (a no ser que hagas el mismo tipo de tareas, supongo). Y no he encontrado una introducción sencilla y clara a este tema (¿quizás porque no la estaba buscando realmente?) )))))))

 

4. encapsulación.

Aquí se oye a menudo: "¿Por qué necesitamos hacer miembros de clase enterrados en OOP? Queremos que todo esté abierto y sea accesible en todas partes".

Pero la OOP no obliga a que todos los miembros estén cerrados. Es el programador quien debe decidir qué debe ocultarse y qué no.

Y normalmente ocultan aquellas cosas que deben ser ocultadas para reducir la probabilidad de corrupción accidental de los datos.

Por ejemplo, tenemos un botón, que se puede configurar en cualquier color.

class ColorButton
{
   color myColor;

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

   color GetColor() const
   {
      return myColor;
   }

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

   void Update();
};

Podemos hacer que la variable myColor esté abierta y cambiar el color del botón en cualquier momento mediante una simple asignación.

Pero la asignación de esta variable no hará que el botón se redibuje inmediatamente.

Así que hacemos que la variable myColor sea privada. Y para cambiar el color, llamamos a la función SetColor().

Esta función, además de asignar una variable, indica al sistema que el botón debe ser repintado.

En esta función, puede poner cualquier otra acción necesaria.

La función GetColor() se utiliza para obtener el color del botón. Su llamada no es más cara que una referencia directa a la variable,

porque el compilador puede optimizarlo fácilmente.

 
Koldun Zloy:

4. encapsulación.


¿Estoy en lo cierto al suponer que en este ejemplo se trata, en el argot, de los propios heteros y setores?

 
Roman:

¿Estoy en lo cierto al suponer que en este ejemplo se trata, en el argot, de los propios heters y setors?

Sí. Eso es correcto.

 
No hay getters y setters en el émulo.
 
Dmitry Fedoseev:
No hay getters y setters en emcool.

Esto no lo determina el MQL, sino el programador. Si él quiere, lo harán.

 
Ihor Herasko:

Esto no lo determina el MQL, sino el programador. Si él quiere, lo harán.

El lenguaje de programación lo determina.

Razón de la queja: