• 第26条:勿在分类中声明属性


    属性是封装数据的方式(参见第6条)。

    属性只是定义实例变量及相关存取方法所用的“语法糖”,所以也应遵循同实例变量一样的规则。

    分类机制,应该将其理解为一种手段,目标在于扩展类的功能,而非封装数据。

    尽管从技术上说,分类里也可以声明属性,但这种做法应该尽量避免。

    原因是:除了“class-continuation分类”(参见第27条)之外,其他分类都无法向类中新增实例变量,因此,它们无法把实现属性所需的实例变量合成出来。

    所以开发者需要在分类中为该属性实现存取方法。

    1)此时可以把方法声明为@dynamic,也就是说,这些方法等到运行期再提供,编译器目前是看不见的。如果决定使用消息转发机制(参见第12条)在运行期拦截方法调用,并提供其实现,那么或许可以采用这种做法。

     

    2)关联对象(参见第10条)能够解决在分类中不能合成实例变量的问题。

    缺点:相似的代码要写很多遍,而且内存管理问题上容易出错。

    例:

    #import <objc/runtime.h>

    static const char *kFriendsPropertyKey = "kFriendsPropertyKey";

    @implementation Person(Friendship)

    -(NSArray*)friends {

      return objc_getAssociatedObject(self, kFriendsPropertyKey);

    }

    -(void)setFriends:(NSArray*)friends {

      objc_setAssociaedObject(self, kFriendsPropertyKey, friends, OBJC_ASSOCIATION_NONATOMIC);

    }

    @end

    3、只读属性可以在分类中使用。属性可以不需要由实例变量来实现。

    由于只读属性在.m中只有一个getter方法,

    即实现了该属性所需的全部方法,所以编译器不会再为属性自动合成实例变量。也就满足上面的条件了,编译器也就不会发出警告信息。

    总结:

    即便这3种方法可以实现,但不推荐。

    而应该把封装数据所用的全部属性都定义在主接口里。

    在“class-continuation分类”之外的其他分类中,可以定义存取方法,但尽量不要定义属性。

  • 相关阅读:
    Shell编程之数值运算(二) Theletter
    Shell编程检测某个服务是否运行实例 Theletter
    Shell编程之条件测试与比较(详解) Theletter
    eclipse中svn提交时报Previous operation has not finished; run 'cleanup' if it was interrupted错误的解决方法
    Jsp连接打印机
    Jsp中table导出到excel
    java创建图片验证码
    java利用映射表名称反射创建实体类并赋属性值
    基于方法的LINQ语句
    opencv中cvCreateImage大图片时出错
  • 原文地址:https://www.cnblogs.com/Pikdays/p/5739795.html
Copyright © 2020-2023  润新知