L'EOP pour les écoliers.

 

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

Ce sujet comprendra des exemples très simples d'utilisation de la POO.

Les questions des programmeurs novices sont les bienvenues. Ceux qui veulent vraiment comprendre la POO.

Les "petits malins" qui pensent que je fais quelque chose de mal, commencez vos propres fils de discussion et faites-le là. Personne n'a besoin de toi ici.

Les disputes sur la nécessité ou l'inutilité de la POO ne sont pas non plus pertinentes ici.

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


1 Supposons que nous fassions quelque chose avec des points dans le plan de coordonnées.

Supposons qu'il n'y en ait que 10.

Il existe plusieurs façons de les stocker en mémoire.

Comme ça :

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

Ou comme ça :

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

Ou comme ça :

double points[10][2];

Mais c'est beaucoup plus pratique de le faire de cette façon :

struct POINT
{
  double x;
  double y;
};

POINT points[10];

Nous avons un nouveau type de données, qui est un point sur un plan.

Nous travaillons avec un point comme une entité distincte.

À titre d'exemple, nous écrivons une fonction qui calcule la distance entre des points.

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 cette façon, la POO nous donne la possibilité de programmer dans un langage de tâches.


Nous continuons...

 

2. Polymorphisme.

Supposons que nous ayons ce code :

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;

Dans ces trois cas, il y a trois fonctions d'addition différentes derrière le signe plus.

C'est ce qu'on appelle le polymorphisme.

La POO nous permet d'étendre cette action à d'autres données.

Par exemple, nous avons une classe de matrice. Il est situé dans le fichier matrix.mqh

Ensuite, nous pouvons écrire ce code :

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

Ici, la POO nous permet de diviser la responsabilité entre les différentes parties du programme.

Lorsque nous écrivons une classe matricielle, nous ne pensons pas à la façon dont elle sera utilisée.

Mais lorsqu'il est écrit et débogué, nous l'utilisons dans diverses tâches sans penser aux règles d'addition et de multiplication des matrices.

On met juste + et *.


A suivre ...

 

3. Fonctions virtuelles.

Supposons que nous ayons écrit plusieurs classes représentant des formes géométriques.

Ils héritent tous d'une classe de 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();
};

Nous pouvons mettre toutes ces formes dans un tableau si nous déclarons un tableau de pointeurs vers la classe de base.

Shape* shapes[10];

Dans la fonction Init(), nous remplissons ce tableau.

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 fonction OnPaint() est appelée lorsque nous devons afficher toutes les formes.

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

Nous parcourons en boucle toutes les formes et appelons la fonction Draw() pour chacune d'entre elles.

Pour chaque forme, nous appelons sa propre fonction qui sait comment dessiner cette forme particulière.

C'est l'essence même des fonctions virtuelles.

Et bien sûr, n'oubliez pas de les supprimer à la fin.

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


Pour continuer ...

 

Nan, ils (l'écolier) ne comprendraient pas. Surtout pas une sorte de matrice. Ils diront : pourquoi avons-nous besoin de ce polymorphisme... une sorte de polymorphisme ? D'autant plus que dans l'emculus son efficacité n'est apparente que s'il y a au moins 10 variantes. au moins 10 variantes.

Nous devrions probablement commencer par la possibilité de combiner fonctions et variables - pour se débarrasser des variables globales et de la confusion qui y est associée.

 
Dmitry Fedoseev:

Nan, ils (l'écolier) ne comprendraient pas. Surtout pas une sorte de matrice. Ils diront : pourquoi avons-nous besoin de ce polymorphisme... une sorte de polymorphisme ? D'autant plus que dans l'emculus son efficacité n'est apparente que s'il y a au moins 10 variantes. au moins 10 variantes.

Peut-être devrions-nous commencer par la possibilité de combiner fonctions et variables - pour nous débarrasser des variables globales et de la confusion qui leur est associée.

Je suppose que ))))

Personnellement, je ne comprends toujours pas si cette OOP est nécessaire ou non. Je ne vois pas d'avantages évidents (sauf si vous effectuez le même type de tâches, je suppose). Et je n'ai pas trouvé d'introduction simple et claire à ce sujet (peut-être parce que je ne la cherchais pas vraiment ?) ))))))).

 

4. encapsulation.

On peut souvent entendre ici : "Pourquoi avons-nous besoin de faire des membres de classe enterrés dans la POO ? Nous voulons que tout soit ouvert et accessible partout."

Mais la POO n'oblige pas à rendre tous les membres fermés. C'est au programmeur de décider ce qui doit être caché et ce qui ne doit pas l'être.

Et généralement, ils cachent les choses qui doivent être cachées pour réduire la probabilité d'une corruption accidentelle des données.

Par exemple, nous avons un bouton, qui peut être réglé sur n'importe quelle couleur.

class ColorButton
{
   color myColor;

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

   color GetColor() const
   {
      return myColor;
   }

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

   void Update();
};

Nous pourrions ouvrir la variable myColor et changer la couleur du bouton à tout moment par une simple affectation.

Mais l'affectation de cette variable n'entraînera pas le redessin immédiat du bouton.

Nous rendons donc la variable myColor privée. Et pour changer la couleur, nous appelons la fonction SetColor().

Cette fonction, en plus d'assigner une variable, indique au système que le bouton doit être repeint.

Dans cette fonction, vous pouvez mettre toute autre action nécessaire.

La fonction GetColor() est utilisée pour obtenir la couleur du bouton. Son appel n'est pas plus coûteux qu'une référence directe à la variable,

car le compilateur peut facilement l'optimiser.

 
Koldun Zloy:

4. encapsulation.


Ai-je raison de supposer que dans cet exemple, il s'agit, en argot, des très hétéros et des setors ?

 
Roman:

Ai-je raison de supposer que dans cet exemple il s'agit, en argot, des mêmes heters et setors ?

Oui. C'est exact.

 
Il n'y a pas de getters et setters dans l'emculus.
 
Dmitry Fedoseev:
Il n'y a pas de getters et setters dans emcool.

Ceci n'est pas déterminé par le MQL, mais par le programmeur. S'il le veut, ils le feront.

 
Ihor Herasko:

Ceci n'est pas déterminé par le MQL, mais par le programmeur. S'il le veut, ils le feront.

C'est le langage de programmation qui le détermine.