• 分类 类扩展 继承 协议 委托


    分类 类扩展 继承 协议 委托

    分类(Category)

    • 分类是向原类中增加一组方法和实现,分类是方法不是类,故无需继承父类,但有自己的.h和.m文件
    • 分类只能向原类中增加方法,或者重写原类的方法。分类中定义的方法会成为原类的一部分,和原类中声明的方法没有任何区别。
    • 分类覆盖原类的方法,也可以使用super调用原类的该方法。如不调用super,子类在调父类方法时,会直接调用分类中重写的方法,不再去调原类的方法。
    • 因为分类不能添加实例变量,而get/set的实现必须使用_实例变量。所以分类中的@property只会生成getter setter方法的声明,不会自动合成_实例变量和get/set方法的实现。
    • 类.h中定义的方法必须实现,但分类.h中定义的方法,可以不实现(如作非正式协议或前向引用时)
    • 重写原类的同名方法,调用时分类的优先级高。如果在类目中覆盖现有类的方法,这样会引起super的消息的断裂,因为类目中的方法具有更高的优先级,因此,一般不要覆盖现有类中的方法。
    • 如果单独创建分类,则分类.h中声明方法属于公开的。
    • 分类如果写在原类.h中,声明的方法是公开的。分类如果写在原类.m中,声明的方法是私有的。
    • 分类向原类中添加的方法也会被子类继承
    • 分类和类扩展也可以遵守协议
    • 类别主要有3个作用:
      (1)将类的实现分散到多个不同文件或多个不同框架中(这时一般将分类写到原类的.h中,对原类分门别类)。
      (2)创建对私有方法的前向引用。(类.h中未声明,但存在于.m中的私有方法,通过在分类.h中声明一下。不用再分类.m中实现,在使用类中同时导入原类.h和分类.h就可以调用私有方法了)
      (3)向对象添加非正式协议。(尖括号是正式协议,圆括号的类别是非正式协议,非正式协议的方法可以不实现)
    •  ### 分类妙用1:给原类增加新的方法接口和实现

       在不知道某个原类.m的具体实现时(如系统类or封装成.a的类,都只暴露原类.h给我们使用,看不到原类.m实现代码), 在这种情况下,我们仍然可以通过 分类来给原类添加新的方法,具体做法是:在分类.h中声明方法接口,在分类.m中写方法实现代码,在需要使用的地方,导入分类.h,然后就可以调用新增的方法,而不会编译报错! 

       ### 分类妙用2:重写原类方法 

       如果创建分类仅仅是为了重写原类中的方法,那么该分类可以不需要.h文件。并且也不需要在任何地方导入分类.h,只需要将分类.m拖入项目中,编译器在编译链接时就会覆盖原类的方法实现!

       而且可以将多个分类.m防止在一个统一的.m文件中,例如: BYFoundationLog.m中放置了NSArray、NSDictionary的分类!

       

       ### 分类妙用3:将某个类的私有方法变为公开方法,此种用法必须同时具备分类.h和分类.m,并且在需要用的地方导入分类.h 

       Cocoa没有任何真正的私有方法。只要知道对象支持的某个方法的名称,即使该对象所在的类的接口中没有该方法的声明,你也可以调用该方法。不过这么做编译器会报错,但是只要新建一个该类的类别,在类别.h文件中写上原始类该方法的声明,类别.m文件中什么也不写,就可以正常调用私有方法了。这就是传说中的私有方法前向引用。 所以说cocoa没有真正的私有方法。

       

       ### 总结:正式因为OC 分类具备以上强大又特殊的性能,使得OC分类成为其他变成语言都没有的特色之一,另外OC分类也体现了OC是一门动态语言!

    类扩展(Extensions)

    • 类扩展和协议形式类似,都只有.h文件。但类扩展属于某个类的声明,协议不属于任何类,只是一组方法的声明。
    • 不产生新类,只有.h文件,可以向原类中添加实例变量和方法。
    • 类扩展和分类都可以遵守协议
    • 类扩展中声明的方法必须实现,否则编译报警告。
    • 类扩展如果独立写一个文件,则声明的变量/属性/方法都是公开的,作用和类.h基本一样
    • 类扩展如果写在类.m文件中,则类扩展中声明的实例变量/属性/方法都属于类私有,不能在其他类和子类中访问。
    • 类扩展就像类.h文件,不管放在类.m开头,还是单独写成类扩展.h文件,其中声明的方法必须在原始类.m进行实现。 类扩展中的@property属性会自动生成实例变量、get/set方法的声明和实现(在原始类.m中写的类扩展,自动生成的属性的实例变量/get&set方法的声明/实现都是私有的,只能在原始类.m中使用。而在单独成文件的类扩展.h中写上@property属性,那么它和在原始类.h中写的属性完全一样,会自动在原始类.h中生成实例变量和get/set的声明,在原始类.m中合成get/set的实现,而且对外是公开的。)

    类继承/子类(Inherit)

    • 产生了新类
    • OC类只能有一个父类,属于单继承。
    • 子类继承父类所有的实例变量、属性、方法(包括.m中的私有的),但是无法直接访问父类.m中私有的的变量/属性/方法,可以理解这些私有的xxx仅在父类.m中有效,而子类中已经超过它们的作用域,故不能访问。
    • 可以继续给子类添加实例变量。
    • 子类可重写父类(即声明和父类同名的方法),调用重写的同名方法,优先调用子类中方法。

    协议(Protocol)

    • 不属于哪个类,只是定义一组方法,只有.h文件,一般直接写在某个类的.h文件中,也可以单独写成一个xxx.h文件
    • 声明的@property只会生成getter setter方法的声明,没地方生成实例变量和get/set的实现。
    • 只声明方法,由遵守协议的代理实现方法
    • 协议支持多继承,即一个类可以遵守多个协议(弥补了OC单继承的不足),但一个类只能继承一个类。

    委托代理(delegate)

    • 一种程序设计思想,主要用于解耦

    补充:

    通常在一个类Person.h文件中写上@property(nonatomic,copy) NSString *name;这样的属性,那么Xcode编译器会自动帮我们

    在Person.h中生成@protected  NSString *_name;实例变量,和_name的get/set方法的声明代码。而且默认会在Person.m中生成_name的get/set方法的实现。

    如果我们不希望Xcode在Person.m中自动生成get/set方法的实现,我们可以在@implementation 下方写上 @dynamic  name;语句,

    意思告诉Xcode:属性name的get/set方法的实现部分由我自己动态生成,使用这个语句,通常会配合使用运行时,在程序运行时,动态生成get/set的实现。

    iOS开发者交流群:180080550
  • 相关阅读:
    执行脚本,且以脚本名保存log
    循环读取寄存器(QSFP-DD)并且分别保存log
    shell脚本添加脚本执行时间和当前运行次数current running time
    软件后门种植
    IPC$管道的利用与远程控制
    古典密码-维吉尼亚密码实验
    古典密码之乘法密码
    古典密码之凯撒密码
    密码破解工具Brutus
    ASPack壳脱壳实验
  • 原文地址:https://www.cnblogs.com/stevenwuzheng/p/5456738.html
Copyright © 2020-2023  润新知