oc——类——数据成员

数据成员

类只有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数据成员
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值