Ojective-C学习笔记(4)关于面向对象编程

在面向对象编程中使用间接

在学习之前,先看一个过程式编程的例子。

//
//  main.m
//  OOP
//
//  Created by ccyag on 21/4/18.
//  Copyright © 2018年 ccyag. All rights reserved.
//

#import <Foundation/Foundation.h>

typedef enum{
    kCircle,
    kRectangle,
    kTriangle
} ShapeType;

typedef enum{
    kRed,
    kGreen,
    kBlue
} ShapeColor;

NSString *colorName(ShapeColor color){
    switch (color) {
        case kRed:
            return @"red";
            break;
        case kGreen:
            return @"green";
            break;
            case kBlue:
        return @"blue";
            break;
    }
}

typedef struct{
    int x, y, widht, height;
} ShapeRect;

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

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

void drawRectangle(ShapeRect bounds, ShapeColor color){
    NSLog(@"drawing a rectangle at(%d %d %d %d) in %@",
          bounds.x, bounds.y, bounds.widht, bounds.height, colorName(color));
}

void drawTriangle(ShapeRect bounds, ShapeColor color){
    NSLog(@"drawing a triangle at(%d %d %d %d) in %@",
          bounds.x, bounds.y, bounds.widht, bounds.height, colorName(color));
}

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].color);
                break;
            case kRectangle:
                drawRectangle(shapes[i].bounds, shapes[i].color);
                break;
            case kTriangle:
                drawTriangle(shapes[i].bounds, shapes[i].color);
                break;
        }
    }
}

int main(int argc, const char * argv[]) {
    Shape shapes[3];
    ShapeRect rect0 = {0, 0, 30, 30};
    shapes[0].type = kCircle;
    shapes[0].color = kRed;
    shapes[0].bounds = rect0;
    
    ShapeRect rect1 = {50, 50, 60, 80};
    shapes[1].type = kRectangle;
    shapes[1].color = kGreen;
    shapes[1].bounds = rect1;
    
    ShapeRect rect2 = {100, 100, 120, 150};
    shapes[2].type = kTriangle;
    shapes[2].color = kBlue;
    shapes[2].bounds = rect2;
    
    drawShapes(shapes, 3);
    return 0;
}

运行结果如下:

2018-04-21 14:27:33.330017+0800 OOP[4205:624974] drawing a circle at(0 0 30 30) in red
2018-04-21 14:27:33.330242+0800 OOP[4205:624974] drawing a rectangle at(50 50 60 80) in green
2018-04-21 14:27:33.330255+0800 OOP[4205:624974] drawing a triangle at(100 100 120 150) in blue

这是一段面向过程的代码,功能很简单,实现了图形的绘制功能,每一种图形都有自己的颜色,形状和坐标位置,用到了C语言中的枚举和结构体。
这段代码中有很多重复的地方,而且扩展和维护起来很困难。比如添加一个椭圆图形,完整代码如下:

#import <Foundation/Foundation.h>

typedef enum{
    kCircle,
    kRectangle,
    kTriangle,
    kEllipse
} ShapeType;

typedef enum{
    kRed,
    kGreen,
    kBlue
} ShapeColor;

NSString *colorName(ShapeColor color){
    switch (color) {
        case kRed:
            return @"red";
            break;
        case kGreen:
            return @"green";
            break;
            case kBlue:
        return @"blue";
            break;
    }
}

typedef struct{
    int x, y, widht, height;
} ShapeRect;

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

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

void drawRectangle(ShapeRect bounds, ShapeColor color){
    NSLog(@"drawing a rectangle at (%d %d %d %d) in %@",
          bounds.x, bounds.y, bounds.widht, bounds.height, colorName(color));
}

void drawTriangle(ShapeRect bounds, ShapeColor color){
    NSLog(@"drawing a triangle at (%d %d %d %d) in %@",
          bounds.x, bounds.y, bounds.widht, bounds.height, colorName(color));
}

void drawEllipse(ShapeRect bounds, ShapeColor color){
    NSLog(@"drawing a Ellipse at (%d %d %d %d) in %@",
          bounds.x, bounds.y, bounds.widht, bounds.height, colorName(color));
}

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].color);
                break;
            case kRectangle:
                drawRectangle(shapes[i].bounds, shapes[i].color);
                break;
            case kTriangle:
                drawTriangle(shapes[i].bounds, shapes[i].color);
                break;
            case kEllipse:
                drawEllipse(shapes[i].bounds, shapes[i].color);
        }
    }
}

int main(int argc, const char * argv[]) {
    Shape shapes[4];
    ShapeRect rect0 = {0, 0, 30, 30};
    shapes[0].type = kCircle;
    shapes[0].color = kRed;
    shapes[0].bounds = rect0;
    
    ShapeRect rect1 = {50, 50, 60, 80};
    shapes[1].type = kRectangle;
    shapes[1].color = kGreen;
    shapes[1].bounds = rect1;
    
    ShapeRect rect2 = {100, 100, 120, 150};
    shapes[2].type = kTriangle;
    shapes[2].color = kBlue;
    shapes[2].bounds = rect2;
    
    ShapeRect rect3 = {200, 200, 40, 80};
    shapes[3].type = kEllipse;
    shapes[3].color = kRed;
    shapes[3].bounds = rect3;
    
    drawShapes(shapes, 4);
    return 0;
}

需要修改很多地方,修改的地方越多,程序越容易出错。面向对象编程很好地解决了这些问题。在下一篇随笔中将实现面向对象编程。

posted @ 2018-04-21 14:46  陈道长  阅读(161)  评论(0编辑  收藏  举报