官术网_书友最值得收藏!

4.4 屬性

面向對象編程概念中,屬性表示對象的特性,如名稱、顏色、速度、尺寸、位置等。在Objective-C中,常用的屬性定義方式有兩種:

? 第一種是使用@proeprty和@synthesize指令快速創(chuàng)建,稱為存儲屬性(stored property)。

? 另一種是使用setter和getter方法創(chuàng)建,稱為計算屬性(compute property)。

下面我們就分別介紹這兩種創(chuàng)建屬性的方式。

■4.4.1 使用@proeprty和@synthesize指令

在類中,使用@proeprty和@synthesize指令定義屬性主要有兩個步驟。

第一步,在類的接口部分使用@property指令聲明屬性的類型和名稱,如下面的代碼(CRobot.h文件)。

    @interface CRobot : NSObject
    @property NSString* name;
    // 其他代碼
    @end

如果多個屬性的類型是一樣的,我們還可以使用一個@property指令同時聲明,如下面的代碼。

    @property float xPos, yPos;

代碼中同時定義了float類型的兩個屬性:x和y。

接下來,我們在類的實現(xiàn)部分使用@synthesize指令同步這些屬性,如下面的代碼。

    @implementation CRobot
    @synthesize name;
    @synthesize xPos, yPos;
    // 其他代碼
    @end

請注意,在類的實現(xiàn)部分,使用@synthesize指令同步屬性時,不再需要指定屬性的類型;這樣一來,我們可以將不同類型的屬性寫成一行,如下面的代碼。

    @synthesize name, xPos, yPos;

應用中,我們通過圓點運算符(.)來訪問對象的屬性,如下面的代碼。

    CRobot *robot5 = [[CRobot alloc] init];
    robot5.name = @"No.5";
    robot5.xPos = 5.0;
    robot5.yPos = 6.0;
    NSLog(@"機器人%@的位置在(%f, %f)", robot5.name,
        robot5.xPos, robot5.yPos);

使用@property和@synthesize指令創(chuàng)建屬性的確非常方便,但也有一些不足,最明顯的就是在設置屬性值時,在類的內(nèi)部無法對數(shù)據(jù)進行更多的操作,只能在設置屬性值之前對數(shù)據(jù)進行處理,如正確性檢查。

如果需要在設置屬性值的同時,在類的內(nèi)部可以對數(shù)據(jù)進行更多的處理,應使用getter和setter方法來創(chuàng)建屬性。

■4.4.2 使用setter和getter方法

使用setter和getter方法創(chuàng)建類的屬性時,一般會使用一個內(nèi)部的實例變量來保存屬性的數(shù)據(jù),然后,我們會定義相應的方法設置和讀取這個數(shù)據(jù),如下面的代碼,我們首先在類的接口部分聲明一個屬性(speed)的設置和讀取方法。

    @interface CRobot : NSObject
    -(float) speed;
    -(void) setSpeed:(float)s;
    // 其他代碼
    @end

接下來,我們會在類的實現(xiàn)部分定義屬性數(shù)據(jù)實例變量,以及屬性的設置和讀取方法,如下面的代碼。

    @implementation CRobot
    {
        float _speed;
    }
    -(float) speed
    {
        return _speed;
    }
    -(void) setSpeed:(float)s
    {
        _speed = fabs(s);
    }
    // 其他代碼
    @end

在這個代碼中,我們需要注意以下幾個問題。

? 計算屬性一般會在內(nèi)部使用一個實例變量保存真正的數(shù)據(jù),如代碼中的_speed實例變量。

? getter方法用于獲取屬性值,其方法名也就是屬性的名稱,而它的實現(xiàn)也相對簡單,一般來講,直接返回對應的實例變量的數(shù)據(jù)就可以了。

? setter方法用于設置屬性值,其命名規(guī)則是“set+屬性名”,其中,屬性名首字母大寫。對于本例中的setter方法實現(xiàn),使用了比較簡單的處理方法,我們約定物體的速度不能是負數(shù),所以,直接將傳入數(shù)據(jù)的絕對值賦值給了_speed實例變量。這是特殊的處理方式,在開發(fā)工作中,我們可以根據(jù)需要對傳入的數(shù)據(jù)進行檢查和再加工。

實際上,游戲里角色的速度經(jīng)常被設置為負數(shù)!為什么?后續(xù)內(nèi)容將為您揭曉答案。

使用getter和setter方法定義的屬性,同樣可以使用圓點運算符(.),如下面的代碼。

    CRobot *robot5 = [[CRobot alloc] init];
    robot5.name = @"五號";
    robot5.speed = 50.0;
    NSLog(@"%@ 的速度是 %f km/h", robot5.name, robot5.speed);

此外,我們也可以看到,使用setter和getter方法定義的屬性,其本質(zhì)上還是方法,所以,我們也可以使用方法的形式來調(diào)用它們,但出于實際功能上的考慮,我們還是應該對屬性和方法的應用加以區(qū)分。

關于屬性,還有一個小秘密,使用@property和@synthesize指令創(chuàng)建的屬性,同樣可以使用方法的形式來操作,其原因是,在Objective-C的底層,屬性是通過方法實現(xiàn)的,這是在編譯階段自動完成的。如下面的代碼,我們使用方法的形式來訪問name屬性。

    CRobot *robot5 = [[CRobot alloc] init];
    [robot5 setName:@"No.5"];
    NSLog(@"%@", [robot5 name]);
主站蜘蛛池模板: 克山县| 龙泉市| 施甸县| 尼勒克县| 琼结县| 莱西市| 喜德县| 江都市| 雅安市| 嘉义县| 商丘市| 布尔津县| 界首市| 介休市| 徐汇区| 洪雅县| 定兴县| 玉屏| 白沙| 紫阳县| 年辖:市辖区| 德清县| 垦利县| 西乌珠穆沁旗| 邹城市| 黄石市| 上林县| 中卫市| 瑞金市| 泰兴市| 太白县| 中方县| 唐河县| 龙口市| 布尔津县| 丹棱县| 德化县| 孟津县| 舒兰市| 临洮县| 贵南县|