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

4.4 屬性

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

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

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

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

■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。

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

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

請注意,在類的實現部分,使用@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指令創建屬性的確非常方便,但也有一些不足,最明顯的就是在設置屬性值時,在類的內部無法對數據進行更多的操作,只能在設置屬性值之前對數據進行處理,如正確性檢查。

如果需要在設置屬性值的同時,在類的內部可以對數據進行更多的處理,應使用getter和setter方法來創建屬性。

■4.4.2 使用setter和getter方法

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

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

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

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

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

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

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

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

實際上,游戲里角色的速度經常被設置為負數!為什么?后續內容將為您揭曉答案。

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

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

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

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

    CRobot *robot5 = [[CRobot alloc] init];
    [robot5 setName:@"No.5"];
    NSLog(@"%@", [robot5 name]);
主站蜘蛛池模板: 镇江市| 昌平区| 吴川市| 涞源县| 尼木县| 马鞍山市| 中超| 鹿泉市| 镇安县| 正安县| 广灵县| 板桥市| 华宁县| 夹江县| 深圳市| 婺源县| 麻栗坡县| 夏津县| 门头沟区| 额尔古纳市| 朝阳县| 塔城市| 炉霍县| 永清县| 嘉祥县| 富川| 霸州市| 壤塘县| 达孜县| 青铜峡市| 娄底市| 伊宁县| 阳谷县| 武强县| 北流市| 余庆县| 中牟县| 武胜县| 许昌县| 石棉县| 长春市|