@property命名时的要点与要注意的问题

1、@property命名规范

(1)用@property的命名规范一:在@interface的{}定义“成员类型 _成员名”格式的成员变量,@property 成员类型 成员名;在实现中用@synthesize 成员名=_成员名;访问方式:对象名/self/super . 成员名 注意:@synthesize 成员名=_成员名;表示访问的是”_成员名”这个成员变量,即为“_成员名”这个变量提供了set与get方法,且方法名以不带下划线的成员名为主即 set+成员名(首字母大写)和成员名的set/get方法。这种规范举例如下:假设类声明中:@interface A{int _age; } @property int age; @end 且在类声明中@implementation A @synthesize age=_age; @end 这种情况下系统将为_age提供一个方法名为“setAge”的set方法和一个方法名为“age”的get方法。

(2)用@property的命名命名规范二:在@interface的{}定义“成员类型 成员名”格式的成员变量,@property 成员类型 成员名;在实现中用@synthesize 成员名;访问方式上同:对象名/self/super . 成员名 此规范举例如下:假设类声明中:@interface A{int age;} @property int age;@end且类的实现部分:@implementation A @synthesize age; @end 这种情况下:系统将直接为age提供一个名为"setAge"的set方法和名为"age"的get方法,简单清楚。

(3)用@property的命名规范三:省去@synthesize部分,即去除与@implementation实现文件中与@interface内@property声明的变量对应的@synthesize部分。然后在类声明的{}中声明一个和@property中声明变量的类型相同且名字为"_变量名(变量名指:@property中声明的变量的名称)" 的实例变量。这样命名的好处是:在省去了对应的@synthesize的情况下,系统将不再重新为@property中的变量提供类型相同且名为"_变量名"的私有实例变量,而是直接为{}内的“_变量名”提供方法名为“set变量名”(变量名首字母大写)的set方法和方法名为“变量名”(首字母不大写)的get方法。 继承此类的子类以及子类的子类不仅可以调用set/get方法来访问这个名为“_变量名”的父类定义的实例变量也可以直接用“super->_变量名”的方式来访问这个带下划线的实例变量。这种规范举例如下:假设类声明中:@interface{ int _age;}@property int age; @end 且@implementation部分不写对应的@synthesize部分。这样系统直接为{}内的_age 提供一个名为"setAge"的set方法和一个名为"age"的get方法。且_age 是protected类型,可以被子类直接用指针访问。

注意:在使用 @synthesize xxx=yyy;(xxx在@property已被声明过)这种方式时,表示为yyy这个绑定的变量提供方法名为 setXxx的set方法和方法名为xxx的get方法。如果yyy在@interface中的{}内没有被声明时,系统会先自动为类提供一个名字为yyy且类型与xxx相同的私有类型的实例变量,再提供以上的set/get方法操作。

2、用@property声明变量并和@synthesize配套使用时的多种情况:

(1)当@property声明的变量和@interface内{}中的变量相同且在@implementation中用@synthesize时没有将声明的此变量绑定别的变量时,这时仅仅为已声明的即{}内的实例变量(默认是protected类型)提供set/get方法。

(2)当@property声明的变量和@interface内{}中的变量相同时但在@implementation中用@synthesize时将声明的此变量绑定了别的变量,这时不是在为@interface内{}中的变量提供set/get方法,而是为绑定的那个变量提供set与get方法。

(3)当@property声明的变量和@interface内{}中的变量不同且在@implementation中用@synthesize时没有将声明的此变量绑定别的变量时,系统将提供一个和这个@property中声明的变量完全相同的私有类型的变量,并以此变量名为参考为此变量自动提供set/get方法。

(4)当@property声明的变量和@interface内{}中的所有变量都不同且在@implementation中用@synthesize时将声明的此变量绑定别的变量时,如果绑定的这个变量与类声明中{}内的某个变量完全相同(包括变量名和类型),系统将为{}内与绑定的变量完全相同的那个变量自动提供set/get方法。如果@interface中{}内没有与绑定的这个变量完全相同的实例变量时,系统将自动提供一个与绑定的这个变量完全相同的私有变量,并以@property中声明的变量名为基准为自动提供的这个私有变量自动生成set/get方法。

注意:无论哪种形式,@property自动提供的所有方法都是公有的;其次@property提供的set与get方法名完全与在@property中声明的变量有关,set方法名都是”set变量名“,变量名的首字母都是大写;get方法都是”变量名“。此变量名仅指@property中声明的变量。

3、当仅有@property声明部分但省去对应的@synthesize实现部分的情况下又分为以下三种形式:

(1)形式一:当@property中的声明的变量与@interface类声明的{}内声明的任何变量都不相同时,系统会自动为这个类提供一个名字为“_变量名”的私有类型的实例变量,并为这个私有的实例变量提供一个方法名为“set变量名(变量名首字母要大写)”的set方法和一个方法名为“变量名”的get方法。此时的“变量名”指前面@property中声明的那个变量的名称。例如:@property int age;系统在当前所述的情况下会自动为类提供一个名为“_age”且为私有类型的int型实例变量,并为这个私有类型的实例变量"_age"提供一个方法名为"setAge"的set方法和一个方法名为"age"的get方法。

(2)形式二:当@property中的声明的变量与@interface类声明的{}内声明的变量有相同的时,仍然与形式一相同,并不会因为变量与{}声明中的变量相同而仅仅为{}内的相同变量提供set/get方法 不要造成这种误解。

(3)形式三:形式一虽然省掉很多代码,但也有很大弊端,例如当我们想让继承此类的子类能直接访问此类的@property声明自动提供的私有类型的实例变量是不可能的。想解除这种弊端有一种很好的方法,就是在此类的声明中{}内提供名字为“_变量名(注意:此变量名为@property中声明的变量名)”的实例变量,系统将不再提供名为“_变量名”的实例变量,而是直接将@property语句与{}内的“_变量名”的实例变量进行了绑定,而且继承此类的子类也可以直接访问此变量。例如:@interface{int _age;} @property int age; @end; 系统将不再自动提供一个名为“_age”的变量,而是为_age提供一个方法名为setAge的set方法和方法名为age的get方法。

注意:当为@property中声明的某变量省去对应的@synthesize部分时,不论什么情况系统都会自动为这个变量提供一个私有类型的实例变量且再为这个私有的实例变量提供set/get方法,具体步骤与形式一完全相同。

4、私有类型的实例变量是不能被子类直接访问的,子类只能通过set/get方法来访问。注意以上情况下那些会产生私有类型的实例变量

5、实质剖析:@property仅仅表示声明,即仅仅声明set/get方法名 假设 @property int xxx; 仅仅表示声明了方法名为setXxx的set方法和方法名为xxx的get方法。即set、get方法名完全由@property声明决定。 而@synthesize 仅仅表示对哪个变量进行实现set与get方法。总之一句话:@property指定set与get方法名,@synthesize指定访问变量。当无@synthesize部分时,系统才提供以下划线开头的私有变量。

6、如果我们手动为变量提供了“set(变量名)”(变量名首字母大写)的set方法或者“变量名”(首字母不大写)的get方法,系统将 不再自动提供set或get方法。也就是说Xcode比较尊重程序员的选择,我们已经为变量提供的方法,Xcode将不再自动生成。

7、在使用@property自动生成set/get方法时,凡是Xcode自动生成的实例变量都是私有类型的。子类是无法直接用self->或super->来访问的。

代码验证(项目一)实例如下:

主要验证手动提供的set/get方法,Xcode不再自动生成:

新建c.h编辑如下:

//
//  c.h
//  @property_3
//
//  Created by apple on 15/8/16.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface C : NSObject
{
    @public
    int  age;
    double height;
}
@property int age;
@property double height;
-(int)age;
-(void)setHeight:(double) height;
@end
编辑c.m代码如下:

//
//  c.m
//  @property_3
//
//  Created by apple on 15/8/16.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "c.h"

@implementation C
@synthesize age,height;
-(int)age{
    return  250;
}
-(void)setHeight:(double) height{
    self->height=500;
}
@end

在main.m中调用如下:

//
//  main.m
//  @property_3
//
//  Created by apple on 15/8/16.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "c.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        C *c=[[C  alloc] init];
        c.age=100; //调用了自动生成的setAge方法为age赋值为100;
        c.height=125;//调用了手动提供的setHeight方法为height赋值为500。
        printf("%d %d %.2lf %.2lf\n",c.age,c->age,c.height,c->height);
        [c release];
    }
    return 0;
}
运行结果如下:



代码验证(项目二)实例如下:

主要验证省去@synthesize部分将会出现的几种情况

新建a.h编辑如下:

//
//  a.h
//  @property_2
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface A : NSObject{
    @public
    NSString* t; //没有给t提供set/get方法
    NSString*  _t;
}
@property (nonatomic,copy) NSString * t;//为{}内的_t提供了名为setT的set方法和名为t的get方法;
@property (nonatomic,copy)NSString * t1;//因为{}内不存在NSString类型的_t1,所以系统先为此类提供私有的实例变量_t1,然后为_t1提供方法名为setT1的set方法和方法名为t1的get方法。
-(void)Test;
@end
编辑a.m代码如下:

//
//  a.m
//  @property_2
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "a.h"

@implementation A
-(void)Test{
    self->t=@"t";
    self->_t=@"_t";
    self->_t1=@"_t1"; //系统提供的_t1是私有类型的,在外部和子类中是无法直接访问的。
    NSLog(@"类存在实例变量:%@\n",self->t);
    NSLog(@"类存在实例变量:%@\n",self->_t);
    NSLog(@"类存在实例变量:%@\n",self->_t1);
    NSLog(@"存在方法self.t:%@\n",self.t);
    NSLog(@"存在方法self.t1:%@\n",self.t1);
}
@end
在main.m文件中调用如下:

//
//  main.m
//  @property_2
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "a.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        A  *a=[[A alloc] init];
        [a Test];
        [a release];
    }
    return 0;
}
运行结果如下:



=============================================================================

代码验证(项目三)实例如下:

验证存在对应的@synthesize部分将会出现的几种情况。

新建a.h编辑如下:

//
//  a.h
//  @property_problem
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface A : NSObject
{
@public
    int  x, _x, _y, y ;
}
@property  int   x,  _x ;
@property  int   y,  _y ;
@property  int   z ;
@property  int   z1 ;
-(void)Test;
@end
编辑a.m如下:

//
//  a.m
//  @property_problem
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import "a.h"
@implementation A
@synthesize x  ; /* 完全可以写到同一个@synthesize声明中用“,”隔开 */
@synthesize _x;
@synthesize y =_y ;
@synthesize _y = y ;
@synthesize z =_z ;
@synthesize z1;
-(void)Test{
    printf("======================成员方法Test检测验证=====================\n");
    printf("self->x = %d\t   self.x = %d\t self->_x = %d\t self._x = %d\t\n", self->x, self.x, self->_x, self._x );
    printf("self->y = %d\t   self.y = %d\t self->_y = %d\t self._y = %d\t\n", self->y, self.y, self->_y, self._y );
    printf("self->_z = %d\t  self.z = %d\t self->z1= %d\t  self.z1 = %d\t\n", self->_z, self.z,self->z1, self.z1); //不存在实例变量z,存在_z
   }
@end

编辑main.m如下:

//
//  main.m
//  @property_problem
//
//  Created by apple on 15/8/15.
//  Copyright (c) 2015年 liu. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "a.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        A *a=[[A alloc] init];
        a.x=100;
        a._x=200;
        a.y=300;
        a._y=400;
        a.z=500;
        a.z1=600;
        NSLog(@"a.x=%d  a->x=%d",a.x,a->x);
        NSLog(@"a._x=%d  a->_x=%d",a._x,a->_x);
        NSLog(@"a.y=%d  a->y=%d",a.y,a->y);
        NSLog(@"a._y=%d  a->_y=%d",a._y,a->_y);
        NSLog(@"a.z=%d  a.z=%d",a.z,a.z);
        NSLog(@"a.z1=%d  a.z1=%d",a.z1,a.z1);
        [a Test];
    }
    return 0;
}

运行结果如下:



分析程序如下图所示:

首先在类的对象方法实现中观察self用.和->访问时的提示


其次在main.m中观察类的对象指针用.和->访问时的提示如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值