黑马程序员——Objective-C学习笔记(一):面向对象

 ——- android培训IOS培训、期待与您交流! ———-



面向对象编程

要理解OOP的灵活性,首先来看一下过程式编程。
下面一个程序假设在屏幕上绘制几何图形,不过用文本输出代替了实际的绘图,:


#import <Foundaion/Foundation.h>
//通过枚举指定可以绘制的图形
typedef enum {
    Circle,//圆形
    Rectangle,//矩形
    Egg,//椭圆形
} ShapeType;

//定义绘制形状时可以使用的颜色
typedef enum {
    RedColor,//红色
    GreenColor,//绿色
    BlueColor,//蓝色
} ShapeColor;
// 描述一个矩形,该矩形指定屏幕上的绘图区域
typedef struct {
    int x;
    int y;
    int width;
    int height;
} ShapeRect;
//综合所有的内容,成为一个整体
typedef struct {
    ShapeType type;
    ShapeColor fillColor;
    ShapeRect bounds;
} Shape;

int main(int argc, char *argv[]) {

    Shape shapes[3]; //声明要绘制的形状的数组

    ShapeRect rect0= { 0, 0, 10, 30 }; //定义绘图空间
    shapes[0].type = Circle; //圆形
    shapes[0].fillColor = RedColor; //红色
    shapes[0].bounds = rect0; //分配绘图空间

    ShapeRect rect1= { 30, 40, 50, 60 }; //定义绘图空间
    shapes[1].type = Rectangle; //矩形
    shapes[1].fillColor = GreenColor; //绿色
    shapes[1].bounds = rect1; //分配绘图空间

    ShapeRect rect2= { 15, 18, 37, 29 }; //定义绘图空间
    shapes[2].type = Egg; //椭圆形
    shapes[2].fillColor = BlueColor; //蓝色
    shapes[2].bounds = rect2; //分配绘图空间

    drawShapes(shapes, 3); //调用drawShapes()函数绘制形状

    return 0; //main函数返回

} //main

drawShapes()中的循环先检查数组中的每个Shape 结构体,再通过switch 语句查看结构体的type 字段并调用适合该形状的绘制函数,传递绘图区域和颜色的参数。代码如下:


void drawShapes(Shape shapes[], int count) {

    for(int i = 0; i < count, i++) {

        switch(shapes[i].type) {

            case Circle:
                drawCircle(shapes[i].bounds,
                           shapes[i].fillColor );
                break;

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

            case egg:
                drawEgg(shape[i].bounds,
                        shape[i].fillColor);
                break;
        }   

    }
} //drawShapes

下面是 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

colorName()函数负责转换传入的颜色值,并返回NSString 字面量,比如 @”red”或 @”blue”。

NSString *ColorName (ShapeColor colorName) {

    swith (colorName) {
        case RedColor:
            return @"red";
            break;

        case GreenColor:
            return @"green";
            break;

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

    return @"No clue";

} //ColorName

drawRectangle()drawEgg() 绘图程序与·drawCircle()·类似。

使用过程式编程时,要花时间连接数据和用来处理该数据的函数。必须注意要为数据使用正确的函数。
这种代码的另一个问题是程序的扩展和维护变得困难了。作为例子,为此程序添加一种新形状:三角形。完成任务必须至少修改程序中4个不同的位置。

首先,在ShapeType enum 枚举的内容中增加Triangle 常量。

typedef enum{
    Circle;
    Rectangle;
    Egg;
    Triangle;   
}ShapeType;

然后编写drawTriangle() 函数

void drawTriangle(ShapeRect bounds,ShapeColor fillColor) {

    NSLog (@"drawing triangle at (%d %d %d %d) in %@",
          bounds.x,
          bounds.y,
          bounds.height,
          colorName(fillColor)
          ) //drawTriangle
}

接下来,在drawShape()switch 语句中增加一个新的case 判断,用于测试当前性状的type值是不是Triangle ,如果通过的话则调用drawTriangle() 函数。

void drawShapes(Shape shapes[], int count) {

    for(int i = 0; i < count, i++) {

        switch(shapes[i].type) {

            case Circle:
                drawCircle(shapes[i].bounds,
                           shapes[i].fillColor );
                break;

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

            case egg:
                drawEgg(shape[i].bounds,
                        shape[i].fillColor);
                break;
            case Triangle:
                drawTriangle(shape[i].bounds,
                             shape[i].fillColor);
                break;
        }   

    }
} //drawShapes

最后,为Shape数组增加一个三角形。


int main(int argc, char *argv[]) {

    Shape shapes[4]; //声明要绘制的形状的数组

    ShapeRect rect0= { 0, 0, 10, 30 }; //定义绘图空间
    shapes[0].type = Circle; //圆形
    shapes[0].fillColor = RedColor; //红色
    shapes[0].bounds = rect0; //分配绘图空间

    ShapeRect rect1= { 30, 40, 50, 60 }; //定义绘图空间
    shapes[1].type = Rectangle; //矩形
    shapes[1].fillColor = GreenColor; //绿色
    shapes[1].bounds = rect1; //分配绘图空间

    ShapeRect rect2= { 15, 18, 37, 29 }; //定义绘图空间
    shapes[2].type = Egg; //椭圆形
    shapes[2].fillColor = BlueColor; //蓝色
    shapes[2].bounds = rect2; //分配绘图空间

    ShapeRect rect3= { 15, 18, 37, 29 }; //定义绘图空间
    shapes[3].type = Triangle; //三角形
    shapes[3].fillColor = RedColor; //红色
    shapes[3].bounds = rect3; //分配绘图空间

    drawShapes(shapes, 4); //调用drawShapes()函数绘制形状

    return 0; //main函数返回

} //main

下面是该程序的面向对象版本:

void drawShapes (id shapes[], int count) {

        for (int i = 0; i < count, i++) {

            id shape = shapes[i];
            [shape draw];

        }

} //drawShapes

该程序包含一个循环,用于遍历数组中的每个形状。循环过程中,程序通知形状对象绘制自身。

程序中id表示标识符(identifier),可以用来引用任意类型的对象,本质上是一个指向结构体的指针。

id shape = shapes[i];

是一个指针赋值过程,实际并没有复制shape的全部内容。

[shape draw];

在Objective-C中,方括号还有其他含义: 用于通知某个对象该去做什么。方括号里的第一项是对象,其余部分是需要对象执行的操作。

下面定义Circle类的接口:


@interface Circle: NSObject {

    @private
    ShapeColor fillColor;
    ShapeRect bounds;

}

 - (void) setFillColor: (ShapeColor) fillColor;

 - (void) setBounds: (ShapeRect) bounds;

 - (void) draw;

@end //Circle

@interface Circle: NSObject这一行里的@interface circle

表示这是“新类circle的接口”。: NSObject表示新类circle

承自类NSObject



{

    @private
    ShapeColor fillColor;
    ShapeRect bounds;

}

括号里面的是成员变量

 - (void) setFillColor: (ShapeColor) fillColor;

 - (void) setBounds: (ShapeRect) bounds;

 - (void) draw;

这三行是方法说明,列出了每个方法的名称、方法返回值的类型和某些参数。

@interface部分是用来定义类的公共接口,而使对象运行的代码位于@implementation部分中。

以下是Circle类的实现:

@implementation Circle

 - (void) setFillColor : (ShapeColor) c
   {
        fillcolor = c;
   } //setFillColor

 - (void) setBounds : (ShapeRect) b
   {
        bounds = b;
   } //setBounds

 - (void) draw {

    NSLog (@"drawing Circle at (%d %d %d %d) in %@",
          bounds.x,
          bounds.y,
          bounds.height,
          colorName(fillColor)
          ) 
   } //draw
@end //Circle

使用main()创建圆形、矩形和椭圆。

int main() {

    id shape[3];

    ShapeRect rect0 = {0, 0, 10, 30};
    shapes[0] = [Circle new];
    [shapes[0] setBounds: rect0];
    [shapes[0] setFillColor: RedColor];

    ShapeRect rect1 = {30, 40, 50, 60};
    shapes[1] = [Rectangle new];
    [shapes[1] setBounds: rect1];
    [shapes[1] setFillColor: GreenColor];

    ShapeRect rect2 = {15, 19, 37, 29};
    shapes[2] = [Egg new];
    [shapes[2] setBounds: rect2];
    [shapes[2] setFillColor: BlueColor];

    drawShapes(shapes,3);

    return 0;
} //main

这里使用了id数组而不是shapes 数组。通过向需要创建对象的类发送new 方法,可以创建多个独立对象。

过程式编程通过直接设置struct 的成员来初始化对象,面向对象版本则不是直接设置对象的值,而是而是使用消息请求每个对象设置它自身的边界区域和填充颜色。

下面为该程序的面向对象版本添加绘制三角形的功能。相比于过程式编程的繁琐,这里我们只需要做两件事: 创建新的Triangle 类,然后将triangle对象添加到将要绘制的对象列表中去。

@interface Triangle: NSObject {

    @private
    ShapeColor fillColor;
    ShapeRect bounds;

}

 - (void) setFillColor: (ShapeColor) fillColor;

 - (void) setBounds: (ShapeRect) bounds;

 - (void) draw;

@end //Triangle

@implementation Triangle

 - (void) setFillColor : (ShapeColor) c
   {
        fillcolor = c;
   } //setFillColor

 -  (void) setBounds : (ShapeRect) b
   {
        bounds = b;
   } //setBounds

- (void) draw {

    NSLog (@"drawing Circle at (%d %d %d %d) in %@",
          bounds.x,
          bounds.y,
          bounds.height,
          colorName(fillColor)
          ) 
   } //draw

@end //Triangle

接下来编辑main() 函数来创建三角形。

int main() {

    id shape[4]; //修改shapes数组的大小为4

    ShapeRect rect0 = {0, 0, 10, 30};
    shapes[0] = [Circle new];
    [shapes[0] setBounds: rect0];
    [shapes[0] setFillColor: RedColor];

    ShapeRect rect1 = {30, 40, 50, 60};
    shapes[1] = [Rectangle new];
    [shapes[1] setBounds: rect1];
    [shapes[1] setFillColor: GreenColor];

    ShapeRect rect2 = {15, 19, 37, 29};
    shapes[2] = [Egg new];
    [shapes[2] setBounds: rect2];
    [shapes[2] setFillColor: BlueColor];

    //创建Triangle对象
    ShapeRect rect3 = {47, 32, 80, 50};
    shapes[3] = [Triangle new];
    [shapes[3] setBounds: rect3];
    [shapes[3] setFillColor: RedColor];

    drawShapes(shapes,4);

    return 0;
} //main

这里没有改变drawShapes() 函数或任何其他处理形状的函数。这就是面向对象的强大之处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值