zoukankan      html  css  js  c++  java
  • @property 的本质是什么?ivar、getter、setter 是如何生成并添加到这个类中的

    出题者简介: 孙源(sunnyxx),目前就职于百度

    整理者简介:陈奕龙(子循),目前就职于滴滴出行。

    转载者:豆电雨(starain)微信:doudianyu

    @property 的本质是什么?

      @property = ivar + getter + setter;

    下面解释下:

      “属性” (property)有两大概念:ivar(实例变量)、存取方法(access method = getter + setter)。

    “属性” (property)作为 Objective-C 的一项特性,主要的作用就在于封装对象中的数据。 Objective-C 对象通常会把其所需要的数据保存为各种实例变量。实例变量一般通过“存取方法”(access method)来访问。其中,“获取方法” (getter)用于读取变量值,而“设置方法” (setter)用于写入变量值。这个概念已经定型,并且经由“属性”这一特性而成为 Objective-C 2.0 的一部分。 而在正规的 Objective-C 编码风格中,存取方法有着严格的命名规范。 正因为有了这种严格的命名规范,所以 Objective-C 这门语言才能根据名称自动创建出存取方法。其实也可以把属性当做一种关键字,其表示:

      编译器会自动写出一套存取方法,用以访问给定类型中具有给定名称的变量。 所以你也可以这么说:

      @property = getter + setter;

    例如下面这个类:

    @interface Person : NSObject
    @property NSString *firstName;
    @property NSString *lastName;
    @end

    上述代码写出来的类与下面这种写法等效:

    @interface Person : NSObject
    - (NSString *)firstName;
    - (void)setFirstName:(NSString *)firstName;
    - (NSString *)lastName;
    - (void)setLastName:(NSString *)lastName;
    @end

    ivar、getter、setter 是如何生成并添加到这个类中的?

    “自动合成”( autosynthesis)

    完成属性定义后,编译器会自动编写访问这些属性所需的方法,此过程叫做“自动合成”(autosynthesis)。需要强调的是,这个过程由编译 器在编译期执行,所以编辑器里看不到这些“合成方法”(synthesized method)的源代码。除了生成方法代码 getter、setter 之外,编译器还要自动向类中添加适当类型的实例变量,并且在属性名前面加下划线,以此作为实例变量的名字。在前例中,会生成两个实例变量,其名称分别为 _firstName 与 _lastName。也可以在类的实现代码里通过 @synthesize语法来指定实例变量的名字.

    @implementation Person
    @synthesize firstName = _myFirstName;
    @synthesize lastName = _myLastName;
    @end

    我为了搞清属性是怎么实现的,曾经反编译过相关的代码,他大致生成了五个东西

    1. OBJC_IVAR_$类名$属性名称 :该属性的“偏移量” (offset),这个偏移量是“硬编码” (hardcode),表示该变量距离存放对象的内存区域的起始地址有多远。
    2. setter 与 getter 方法对应的实现函数
    3. ivar_list :成员变量列表
    4. method_list :方法列表
    5. prop_list :属性列表

    也就是说我们每次在增加一个属性,系统都会在 ivar_list 中添加一个成员变量的描述,在 method_list 中增加 setter 与 getter 方法的描述,在属性列表中增加一个属性的描述,然后计算该属性在对象中的偏移量,然后给出 setter 与 getter 方法对应的实现,在 setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转.

  • 相关阅读:
    I40E网卡BUG引起内核异常重启问题分析
    Linux rp_filter配置引起的组播断流问题
    【原创】Intel XL710网卡异常Reset问题复现
    【原创】qlogic网卡软中断不均衡问题分析
    【原创】控制perl和python脚本执行过程中脚本文件是否关闭的方法
    Linux内核d_path函数应用的经验总结
    Intel 82599网卡异常挂死原因
    用slub_track调试use after free问题
    如何获取内核指定线程的调用栈
    使用data breakpoint 追踪地址寄存器被修改的问题
  • 原文地址:https://www.cnblogs.com/starainDou/p/5253199.html
Copyright © 2011-2022 走看看