您的位置:首页 > 其它

oc——类——数据成员

2017-03-14 16:24 78 查看

数据成员

类只有instance object数据成员,没有class object数据成员,因此数据成员存储在class object(非meta-class object)的ivars中
struct objc_ivar {
char *ivar_name                                          OBJC2_UNAVAILABLE;
char *ivar_type                                          OBJC2_UNAVAILABLE;
int ivar_offset                                          OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space                                                OBJC2_UNAVAILABLE;
#endif
}                                                            OBJC2_UNAVAILABLE;

struct objc_ivar_list {
int ivar_count                                           OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space                                                OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_ivar ivar_list[1]                            OBJC2_UNAVAILABLE;
}                                                            OBJC2_UNAVAILABLE;

/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;

struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;

分析:
数据成员结构为objc_ivar,objc_ivar保存着数据成员名(ivar_name),数据成员类型(ivar_type,即数据成员字长),数据成员相对于instance object首地址offset(ivar_offset)和数据成员内存对齐(space),数据成员名唯一确定数据成员
ivars是class object的数据成员list,因此同一class object中,数据成员名不能重名,否则编译器不能确定使用哪个数据成员,二义性错误,或者list中优先search到的数据成员名屏蔽list中之后重名数据成员(ignore之后重名数据成员),oc在编译期避免此情况发生
@interface FBAnimal : NSObject
{
@public
int _food1;
}

@end

@interface FBAnimal ()
{
@public
int _food2;
}

@end

@implementation FBAnimal
{
@public
int _food3;
}

@end

注:_food1,_food2,_food3不能重名

继承体系的数据成员

理论上子类数据成员和父类数据成员相互独立,互不影响,因为数据成员分处于不同的class object中,但在实际中,还是有所限制
@interface FBAnimal : NSObject
{
@public
int _food1;
}

@end

@interface FBAnimal ()
{
@public
int _food2;
}

@end

@implementation FBAnimal
{
@public
int _food3;
}

@end

@interface FBFood : NSObject

@end

@implementation FBFood

@end

primary class interface

@interface FBDog : FBAnimal
{
@public
//FBFood *_food1;
//FBFood *_food2;
//FBFood *_food3;
}

@end

@interface FBDog ()

@end

@implementation FBDog

@end

void member_access()
{
FBFood *food = [[FBFood alloc] init];

FBAnimal *animal1 = [[FBAnimal alloc] init];
FBAnimal *animal2 = [[FBDog alloc] init];
FBDog *dog = [[FBDog alloc] init];

animal1->_food1 = 5;
animal1->_food2 = 5;
animal1->_food3 = 5;

animal2->_food1 = 5;
animal2->_food2 = 5;
animal2->_food3 = 5;

dog->_food1 = 5;
dog->_food2 = 5;
dog->_food3 = 5;
}

注:FBDog的_food1,_food2,_food3与FBAnimal的_food1,_food2,_food3重名,编译error

extension

@interface FBDog : FBAnimal

@end

@interface FBDog ()
{
@public
FBFood *_food1;
FBFood *_food2;
FBFood *_food3;
}

@end

@implementation FBDog

@end

void member_access()
{
FBFood *food = [[FBFood alloc] init];

FBAnimal *animal1 = [[FBAnimal alloc] init];
FBAnimal *animal2 = [[FBDog alloc] init];
FBDog *dog = [[FBDog alloc] init];

animal1->_food1 = 5;
animal1->_food2 = 5;
animal1->_food3 = 5;

animal2->_food1 = 5;
animal2->_food2 = 5;
animal2->_food3 = 5;

dog->_food1 = food;
dog->_food2 = food;
dog->_food3 = food;
}

primary class implementation

@interface FBDog : FBAnimal

@end

@interface FBDog ()

@end

@implementation FBDog
{
@public
FBFood *_food1;
FBFood *_food2;
FBFood *_food3;
}

@end

void member_access()
{
FBFood *food = [[FBFood alloc] init];

FBAnimal *animal1 = [[FBAnimal alloc] init];
FBAnimal *animal2 = [[FBDog alloc] init];
FBDog *dog = [[FBDog alloc] init];

animal1->_food1 = 5;
animal1->_food2 = 5;
animal1->_food3 = 5;

animal2->_food1 = 5;
animal2->_food2 = 5;
animal2->_food3 = 5;

dog->_food1 = food;
dog->_food2 = food;
dog->_food3 = food;
}

总结

数据成员编译期bind,根据instance object指针类型确定数据成员search起始class object
从类体系结构分析,子类数据成员和父类数据成员可重名,但实际中primary class interface中数据成员不能与父类(直接或间接父类)数据成员重名,oc做此限制纯粹从类设计角度考虑,因为作为类提供者,一般只把primary class interface部分open给使用者,而隐藏extension和primary class implementation部分,子类继承父类(直接或间接父类),同理也一般只把primary class interface部分open给使用者,而隐藏extension和primary
class implementation部分,这样一来,如果oc不做上述限制,作为子类使用者,就无法使用父类(直接或间接父类)primary class interface中open给使用者的与子类primary class interface部分同名数据成员了,因为被子类屏蔽了

isa

NSObject包含Class isa数据成员,根据同一class object中,数据成员名不能重名,因此NSObject不允许再自定义isa数据成员
Class isa定义在NSObject的primary class的interface中,因此继承自NSObject的子类(直接或间接子类)primary class interface中不能定义isa数据成员,extension和primary class implementation中则允许定义isa数据成员
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息