Objective-C基础之面向对象编程(OOP)的基础知识(2)——了解过程式编程

OOP真正的革命性在于它使用间接来调用代码。

不是直接调用某个函数,而是间接调用。

只要能够理解这一点,就算是掌握了OOP的内涵了。

其他一切都是通过间接产生的引申结果。



为了理解OOP的灵活性,我们可以先了解什么是过程式编程,这样就可以互相比较。

如果学习过C语言,那么应该可以明白过程式编程是怎么回事。

在过程式编程中,数据通常保存在简单的结构体中(例如C语言的struct元素)。还有一些复杂的数据结构,比如链表和树。当调用一个函数时,你必须将数据传递给函数,函数会处理这些数据。在过程式编程中会频繁地使用到函数,由使用者决定使用什么函数,然后调用它并传递其所需的数据。


以下是一个绘制几何形状的程序,其中省略了绘图代码,并用输出字符代替:

1、必须包含Foundation框架;

2、通过枚举指定几种可以绘制的形状(圆形、矩形和椭圆形):

#import <Foundation/Foundation.h>

typedef enum{
kCircle,
kRectangle,
kEgg } ShapeType;             //枚举形状

3、接着枚举绘制形状时的可用颜色:

typedef enum{  
kRedColor,  
kGreenColor,  
kBlueColor } ShapeColor;      //枚举可用颜色  

4、接着使用一个结构体来描述一个矩形,该矩形指定了屏幕上的绘图区域(在此仅以矩形举例):

typedef struct{
int x, y, width, height;      //绘图坐标点及绘图区域边长
} ShapeRect;        

5、最后,用一个结构体把前面的所有内容包含进来:

typedef struct{
ShapeType type;
ShapeColor fillColor;
ShapeRect bounds;
} Shape;

以上的几个程序块整体地描述了一个形状。

接下来,main()函数声明了要绘制的形状的数组。声明完数组后,数组中的每个元素都通过分配空间进行初始化。以下是示例程序:

int main(int argc, const char * argv[])
{
 Shape shapes[3];

 ShapeRect rect0 = { 0, 0, 10, 30 };
 shapes[0].type = kCircle;
 shapes[0].fillColor = kRedColor;
 shapes[0].bounds = rect0;          //红色圆形

 ShapeRect rect1 = { 30, 40, 50, 60 };
 shapes[1].type = kRectangle;
 shapes[1].fillColor = kGreenColor;
 shapes[1].bounds = rect1;          //绿色矩形

 ShapeRect rect2 = { 15, 18, 37, 29 };
 shapes[2].type = kEgg;
 shapes[2].fillColor = kBlueColor;
 shapes[2].bounds = rect2;          //蓝色椭圆形

 drawShapes(shapes, 3);            //执行绘制动作的函数
 return 0;
} 

其中,main()调用了drawShapes()函数来绘制形状。drawShapes()函数中的循环先检查数组中的每个元素(每个Shapes结构体),再通过switch语句查看结构体的type字段并调用合适的绘制函数:

void drawShapes(Shape shapes[], int count)
{
 for (int i = 0; i < count; i++) 
 {
  switch (shapes[i].type) 
  {
   case kCircle:
    drawCircle (shapes[i].bounds, shapes[i].fillColor);
    break;

   case kRectangle:
    drawRectangle (shapes[i].bounds, shapes[i].fillColor);
    break;

   case kEgg:
    drawEgg (shapes[i].bounds, shapes[i].fillColor);
    break;
  }  
 }
}

举例其中的drawCircle()函数,该函数输出矩形区域的信息及图形颜色:

void drawCircle(ShapeRect bounds, ShapeColor fillColor)
{
 NSLog (@"drawing a circle at (%d %d %d %d) in %@",
    bounds.x, bounds.y,
    bounds.width, bounds.height,
    colorName(fillColor));
}

在drawCircle()函数中,NSLog()中调用的colorName()函数负责转换传入的颜色值,并返回NSString字面量:

NSString *colorName(ShapeColor colorName)
{
 switch (colorName)  
 {
  case kRedColor:
   return @"red";
   break;

 case kGreenColor:
   return @"green";
   break;

 case kBlueColor:
   return @"blue";
   break; 
 }

 return @"no clue";       //@意味着引号内部的字符串应该作为Cocoa的NSString元素来处理。
} 


完整写完程序后,可运行后看到输出结果如下:

drawing a circle at (0 0 10 30) in red
drawing a rectangle at (30 40 50 60) in green
drawing an egg at (15 18 37 29) in blue


按理来说,程序已经正常运行,那就可以了。但是必须注意,如果该程序需要添加一个新的形状,比如三角形,那我们就要花时间把三角形的相关程序重新写到各个程序里。万一要添加形状和颜色很多,那正确地维护程序将变得困难。

我们将这种情况称为,程序的扩展性差

这个时候,我们必须考虑OOP。


猜你喜欢

转载自blog.csdn.net/qq_33737036/article/details/78172810