学童的EOP。

 

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

本专题将包含一些如何使用OOP 的哦简单的例子。

欢迎程序员新手提问。那些真正想了解OOP的人。

认为我做错了事的 "聪明人",自己开个主题,在那里做吧。这里没有人需要你。

关于OOP的必要性和无用性的争议也与此无关。

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


1 假设我们正在对坐标平面上的点做一些事情。

假设只有10个人。

有各种方法将它们存储在内存中。

像这样。

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

或者像这样。

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

或者像这样。

double points[10][2];

但这样做要方便得多。

struct POINT
{
  double x;
  double y;
};

POINT points[10];

我们有一个新的数据类型,它是一个平面上的点。

我们把一个点作为一个独立的实体来工作。

作为一个例子,我们写一个计算点之间距离的函数。

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

这样一来,OOP给了我们用任务语言编程的能力。


我们继续...

 

2.多态性

假设我们有这样的代码。

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;

在这三种情况下,加号背后有三种不同的加法功能。

这就是所谓的多态性。

OOP允许我们将这个动作扩展到其他数据。

例如,我们有一个矩阵类。它位于文件matrix.mqh中。

然后我们可以写出这样的代码。

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

在这里,OOP允许我们在程序的不同部分之间划分责任。

当我们写一个矩阵类时,我们并没有考虑它将如何被使用。

但当它被编写和调试后,我们在各种任务中使用它,而不考虑矩阵加法和乘法的规则。

我们只是把+和*。


待续...

 

3.虚拟功能

假设我们写了几个代表几何图形的类。

所有这些都是继承自一个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();
};

如果我们声明一个指向基类的数组,我们可以把所有这些形状放在一个数组中。

Shape* shapes[10];

在Init()函数中,我们填充这个数组。

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

当我们需要显示所有的形状时,OnPaint()函数被调用。

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

我们循环浏览所有的形状,为每个形状调用Draw()函数。

对于每个形状,我们都会调用它自己的函数,知道如何画出那个特定的形状。

这就是虚拟函数的本质。

当然,也不要忘记在最后删除它们。

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


要继续...

 

不,他们(小学生)不会理解。特别是没有某种矩阵。他们会说:为什么我们需要这种多态性......。某种多态性?更重要的是,在微积分中,只有在至少有10个变体的情况下,其效率才会显现。至少有10种变体。

也许,我们应该从结合函数和变量的可能性开始 - 摆脱全局变量 和与之相关的混乱。

 
Dmitry Fedoseev:

不,他们(小学生)不会理解。特别是没有某种矩阵。他们会说:为什么我们需要这种多态性......。某种多态性?更重要的是,在微积分中,只有在至少有10个变体的情况下,其效率才会显现。至少有10种变体。

也许我们应该从结合函数和变量的可能性开始--摆脱全局变量 和与之相关的混乱。

我想))))

就个人而言,我仍然不明白这种OOP是否有必要。我没有看到任何明显的优势(除非你在做同类的任务,我猜)。而且我还没有找到关于这个话题的简单而清晰的介绍(也许是因为我并没有真正在寻找它?))))))))

 

4.封装。

人们在这里经常可以听到。"为什么我们需要在OOP中制作埋藏的类成员?我们希望所有的东西都是开放的,在任何地方都可以使用"。

但OOP并不强制要求所有的成员都关闭。由程序员来决定哪些必须隐藏,哪些不需要。

而通常他们会隐藏那些必须隐藏的东西,以减少意外数据损坏的概率。

例如,我们有一个按钮,它可以被设置成任何颜色。

class ColorButton
{
   color myColor;

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

   color GetColor() const
   {
      return myColor;
   }

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

   void Update();
};

我们可以让变量myColor打开,通过简单的赋值随时改变按钮的颜色。

但是分配这个变量并不会导致按钮立即被重新绘制。

所以我们把myColor变量设为私有。而为了改变颜色,我们调用SetColor()函数。

这个函数除了分配一个变量外,还告诉系统这个按钮应该被重新画上颜色。

在这个功能中,你可以把任何其他必要的行动。

可以用GetColor()函数来获取按钮的颜色。它的调用并不比直接引用变量更昂贵。

因为编译器可以很容易地对此进行优化。

 
Koldun Zloy:

4.封装。


我认为在这个例子中,用俚语来说,这就是非常的异性恋和异性恋者,这样的假设是否正确?

 
Roman:

我认为在这个例子中,用俚语来说,就是非常的heters和setors,这样的假设是否正确?

是的,这很正确。

 
在emculus中没有getters和setters。
 
Dmitry Fedoseev:
在emcool中没有getters和setters。

这不是由MQL决定的,而是由程序员决定的。如果他想,他们会的。

 
Ihor Herasko:

这不是由MQL决定的,而是由程序员决定的。如果他想,他们会的。

编程语言决定了这一点。