zoukankan      html  css  js  c++  java
  • 《objective-c基础教程》学习笔记(四)—— OC面向对象编程初探

      在上篇博文中,我们编写了一个可以输出不同几何类型的小程序。通过C语言的struct结构体,给大家感受了下,对象的大概样子。

      如果用Obejctive-C的面向对象的特征来实现。那么,drawShape函数应该修改成这样:

    1 void drawShape(id shapes[], int count)
    2 {
    3     for(int i=0;i<count; i++)
    4     {
    5         id shape = shapes[i];
    6         [shape draw];
    7     }
    8 }

      这里,函数上传入的id类型,是指泛型(即:可以用来引用任意类型的对象)。这里的指是一个包含struct结构体的对象。循环体中的id是一个指针类型,指针依次指向数组中的各个几何对象。

      [shape draw]:这个写法比较独特,这里的方括号不是像C语言中一样,表示数组。在Objective-C中,方括号表示通知某个对象去做什么操作(类似消息), 括号前第一个参数表示的是:对象,其余部分表示的是需要对象执行的操作

      那么,[shape draw] 就可以很好的理解为:向对象shape发送draw的消息。

      通过上面改编例子的引入,接下来,就给大家大概的介绍下Objective-C的面向对象的相关内容。在正式转入Objective-C编程之前,先给大家普及下面向对象的几个基本概念。(详细介绍,可以请教度娘或者相关参考书)

        类(Class):是一种表示对象类型的结构体。
        对象(Object):是一种包含值,指向其他类的隐藏指针的结构体。
        实例(Instance):是“对象”的另外一种称呼。
        消息(Message):是对象可以执行的操作,用于通知对象去做什么。
        方法(Method):是为响应消息而运行的代码。
        方法调度(Method Dispatcher):是Objective-C使用的一种机制。
        接口(Interface):是类为对象提供的特性描述。
        实现(Implementation):是使接口能正常工作的代码。
     
      好了,接下来我给大家介绍下,在Objective-C中,如何定义类和方法,以及如何使用。
     
    1). 类的定义
    1 @interface Circle: NSObject
    2 @end

      定义了一个Circle类的接口,“:”表示的是继承NSObject父类。以@interface开始,@end结束。
    注:在Objective-C中,只要看到@符号,就可以将其看中是C的扩展。

    2). 方法的定义

      分为两种,对象方法和静态方法:对象方法定义的时候,最前面用减号静态方法(类方法)定义的时候,最前面用加号
      通俗的讲,类方法,这类方法是可以直接用类名来调用的,它的作用主要是创建一个实例。有人把它称为创建实例的工厂方法。实例方法,要实例化,必须使用类的实例才可以调用的。
    1 @interface Circle: NSObject
    2     -(void) setFillColor : (ShapeColor)fillColor;
    3     -(void) setBounds : (ShapeRect) bounds;
    4     -(void) draw;
    5 @end
      调用的时候,要先实例化。Circle v_circle; -->  v_circle.setFillColor; 那么,什么是静态方法呢?这里给个基本例子:
    1 @interface NSString : NSObject
    2     +(id)string;
    3     +(id)stringWithString:(NSString*)aString;
    4     +(id)stringWithWithCString:(const char*)cString
    5                         encoding:(NSStringEncoding)enc;
    6 @end

      这个可以直接用类名来调用。--> NSString.string;

    PS:上面只是对方法进行了声明,具体的方法还没实现。在定义方法的时候,前一个括号中的表示返回值的类型,后一个表示调用这个方法要传入的参数的类型。

    3). 方法的实现

      一般创建Objective-C项目的时候,会自动创建两个文件。.h结尾的头文件和.m结尾的实现文件(这个.m类似C语言中的.c,C++中的.cpp)。

    实现方法就写在.m结尾的实现文件中,方法如下:

     1 #import "Shapes.h"
     2 @implementation Circle
     3     -(void) setFillColor :(ShapeColor)fillColor
     4     {
     5             ...  //具体实现的代码1
     6     }
     7     -(void) setBounds :(ShapeRect)bounds
     8     {
     9             ... //具体实现的代码2
    10     }
    11     -(void) draw
    12     {
    13             ... // 具体实现的代码3
    14     }
    15 @end

      在Objective-C中,有一种叫中缀符的语法技术。方法的名称和参数可以合在一起。

    例如:

    [circle setFillColor: kRedColor];

    那么,带两个参数的方法如何调用呢?方法如下:

    [textThing setStringValue: @"hello there" color: kBlueColor];

      好了,那么接下来。我们就将上一篇博文中的代码修改成用Objective-C的语法的吧。

      1 //
      2 //  main.m
      3 //  ch4_OOP_Shapes_OC
      4 //
      5 //  Created by pcbeta on 14-11-18.
      6 //  Copyright (c) 2014年 julian. All rights reserved.
      7 //  面向对象的基本实例,绘制几个几何图形,修改成Objective-C版本
      8 //-------------------------------------修改版,修改Objective_C-------------------------------
      9 
     10 /* 1. enum 枚举类型 */
     11 //定义绘制图形的类型: 圆形,矩形,椭圆形
     12 typedef enum{
     13     kCircle,
     14     kRectangle,
     15     kEgg
     16 } ShapeType;
     17 
     18 //定义绘制图形的颜色: 红色,绿色和蓝色
     19 typedef enum{
     20     kRedColor,
     21     kGreenColor,
     22     kBlueColor
     23 } ShapeColor;
     24 
     25 /* 2. struct 结构体 */
     26 //定义图形的基本属性
     27 typedef struct{
     28     int x, y, width, height;
     29 } ShapeRect;
     30 
     31 //定义整体描述的形状
     32 typedef struct{
     33     ShapeType type;
     34     ShapeColor fillColor;
     35     ShapeRect bounds;
     36 } Shape;
     37 
     38 /* 3.定义获取颜色名称的函数 */
     39 NSString *colorName (ShapeColor fillColor)
     40 {
     41     switch(fillColor)
     42     {
     43         case kRedColor:
     44             return @"red";
     45             break;
     46         case kGreenColor:
     47             return @"green";
     48             break;
     49         case kBlueColor:
     50             return @"blue";
     51             break;
     52     }
     53 }
     54 
     55 //定义一个圆和实现方法
     56 @interface Circle : NSObject
     57 {
     58 @private ShapeColor fillColor;
     59     ShapeRect bounds;
     60 }
     61 -(void) setFillColor : (ShapeColor)fillColor;
     62 -(void) setBounds:(ShapeRect) bounds;
     63 -(void) draw;
     64 @end
     65 
     66 @implementation Circle
     67 -(void) setFillColor:(ShapeColor) c
     68 {
     69     fillColor = c; //fillColor为实例变量,为了防止同名,传入的参数要取别名
     70 }
     71 -(void) setBounds:(ShapeRect)b
     72 {
     73     bounds = b;
     74 }
     75 -(void) draw
     76 {
     77     NSLog(@"drawing a circle at (%d %d %d %d) in %@",
     78           bounds.x,
     79           bounds.y,
     80           bounds.height,
     81           bounds.width,
     82           colorName(fillColor));
     83 }
     84 @end
     85 
     86 //定义一个矩形和实现方法
     87 @interface Rectangle : NSObject
     88 {
     89 @private ShapeColor fillColor;
     90     ShapeRect bounds;
     91 }
     92 -(void) setFillColor : (ShapeColor)fillColor;
     93 -(void) setBounds:(ShapeRect) bounds;
     94 -(void) draw;
     95 @end
     96 
     97 @implementation Rectangle
     98 -(void) setFillColor:(ShapeColor) c
     99 {
    100     fillColor = c; //fillColor为实例变量,为了防止同名,传入的参数要取别名
    101 }
    102 -(void) setBounds:(ShapeRect)b
    103 {
    104     bounds = b;
    105 }
    106 -(void) draw
    107 {
    108     NSLog(@"drawing a rectangle at (%d %d %d %d) in %@",
    109           bounds.x,
    110           bounds.y,
    111           bounds.height,
    112           bounds.width,
    113           colorName(fillColor));
    114 }
    115 @end
    116 
    117 //定义一个椭圆和实现方法
    118 @interface Egg : NSObject
    119 {
    120 @private ShapeColor fillColor;
    121     ShapeRect bounds;
    122 }
    123 -(void) setFillColor : (ShapeColor)fillColor;
    124 -(void) setBounds:(ShapeRect) bounds;
    125 -(void) draw;
    126 @end
    127 
    128 @implementation Egg
    129 -(void) setFillColor:(ShapeColor) c
    130 {
    131     fillColor = c; //fillColor为实例变量,为了防止同名,传入的参数要取别名
    132 }
    133 -(void) setBounds:(ShapeRect)b
    134 {
    135     bounds = b;
    136 }
    137 -(void) draw
    138 {
    139     NSLog(@"drawing a egg at (%d %d %d %d) in %@",
    140           bounds.x,
    141           bounds.y,
    142           bounds.height,
    143           bounds.width,
    144           colorName(fillColor));
    145 }
    146 @end
    147 
    148 void drawShape(id shapes[], int count)
    149 {
    150     for(int i=0;i<count;i++)
    151     {
    152         id shape = shapes[i];
    153         [shape draw];
    154     }
    155 }
    156 
    157 int main(int argc, const char * argv[])
    158 {
    159     // 定义三个几何图形的数组
    160     id shapes[3];
    161     // 定义第一个几何图形为 红色的圆形,
    162     ShapeRect rect0 ={0,0,10,30};
    163     shapes[0] =[Circle new];
    164     [shapes[0] setBounds: rect0];
    165     [shapes[0] setFillColor: kRedColor];
    166     
    167     // 定义第二个几何图形为 绿色的矩形,
    168     ShapeRect rect1 ={30,40,50,60};
    169     shapes[1] =[Rectangle new];
    170     [shapes[1] setBounds: rect1];
    171     [shapes[1] setFillColor: kGreenColor];
    172     
    173     // 定义第三个几何图形为 蓝色的椭圆形,
    174     ShapeRect rect2 ={15,18,37,29};
    175     shapes[2] = [Egg new];
    176     [shapes[2] setBounds: rect2];
    177     [shapes[2] setFillColor: kBlueColor];
    178     
    179     drawShape(shapes, 3);
    180     
    181     return 0;
    182 }
    View Code

      在运行上面代码的时候,我发现一个书本上没有提及的问题。那就是如图:

      有两个错误提示,之前以为是代码写的错误。但是反复查阅,还是没有发现问题。

    后来,通过查询错误信息(参考:http://blog.csdn.net/wbw1985/article/details/7644815)。

    找出了错误原因:由于 XCode5.1 中缺省ARC(内存管理的一种模式,后面讲内存管理的时候会详细介绍)就是 ON 的状态,所以编译旧代码的时候往往有"Automatic Reference Counting Issue"的错误信息。

    解决的方法是:将项目编译设置中的“Objectice-C Auto Reference Counteting”设为NO。如下所示:

      设置完之后点击保存,错误提示就消失了。这个时候点击运行按钮,就可以看到运行结果如图:

      但是,通过今天修改过的Objective-C的例子,我们可以看出代码中了有很多地方都是重复的。

    比如定义和实现Circle,Rectangle,Egg的代码,基本都是重复的,这就很很大的优化空间了。

      下篇博文,我们将继续延续这个例子展开。介绍下Objective-C中继承方法的使用。

  • 相关阅读:
    python-Beautiful rose
    python-and和 or用法
    myspl数据库基础
    python 协程
    python-os 模块
    python-logging模块
    异常处理
    面向对象-类中的三个装饰器
    Flask初见
    django中的ContentType使用
  • 原文地址:https://www.cnblogs.com/jianglan/p/4122110.html
Copyright © 2011-2022 走看看