美文网首页
iOS 扩展(Extension)以及和类别(Category)

iOS 扩展(Extension)以及和类别(Category)

作者: 木子雨廷t | 来源:发表于2020-01-10 21:57 被阅读0次
    关于Category 的用法以及底层原理的问题,iOS Category的本质(一)这篇文章已经讲的很清楚了,今天主要讲讲Extension的用法以及和Category的区别。
    类扩展就像匿名的分类一样,除了一样不同的是,类扩展声明必须在@implementation在实现。

    新建一个Cat类,代码如下:

    #import "Cat.h"
    
    @interface Cat ()
    
    /*** 名字 ****/
    @property(nonatomic,copy) NSString *name;
    
    - (void)eatFood;
    
    @end
    
    @implementation Cat
    
    - (void)eatFood{
        
    }
    
    @end
    

    声明的方法必须要实现,不然编译器会提出警告。
    从上面看出,分类类扩展的相似之处是:都可以为类添加一个额外的方法;

    不同之处在于:要添加额外方法,分类必须在第一个@interface中声明方法,并且在@implementation中提供实现,不然运行时出错。而类扩展,你添加的方法是一个required API,如果不去实现,编译器会警告,而且这个方法的声明可以不在第一个@interface中去声明。
    区别:

    分类:是不可以声明实例变量,通常是公开的,文件名通常为:”主类类名+分类类名.h”

    扩展:是可以声明实例变量,是私有的,文件名通常为:”主类类名_扩展标识.h”,注意扩展没有名的。

    区别分类与扩展

    1.都可以在主类中声明使用

    2.通常来讲由于分类不能创建实例变化,本质上与主类有区别,所以不建议写在主类中。

    3.扩展与主类紧密联系在一起,可以创建实例变量,所以通常来讲会把扩展和主类创建在一起。

    4.扩展(Extension)中的方法和属性在编译时就已经存储在类信息中了。类别(Category)中类的方法在运行时才存储在类信息中。

    编译时:

    编译时顾名思义就是正在编译的时候.那啥叫编译呢?就是编译器帮你把源代码翻译成机器能识别的代码.(当然只是一般意义上这么说,实际上可能只是翻译成某个中间状态的语言.比如Java只有JVM识别的字节码,C#中只有CLR能识别的MSIL.另外还有啥链接器.汇编器.为了了便于理解我们可以统称为编译器)

    那编译时就是简单的作一些翻译工作,比如检查老兄你有没有粗心写错啥关键字了啊.有啥词法分析,语法分析之类的过程.就像个老师检查学生的作文中有没有错别字和病句一样.如果发现啥错误编译器就告诉你.如果你用微软的VS的话,点下build.那就开始编译,如果下面有errors或者warning信息,那都是编译器检查出来的.所谓这时的错误就叫编译时错误,这个过程中做的啥类型检查也就叫编译时类型检查,或静态类型检查(所谓静态嘛就是没把真把代码放内存中运行起来,而只是把代码当作文本来扫描下).所以有时一些人说编译时还分配内存啥的肯定是错误的说法.

    运行时:

    所谓运行时就是代码跑起来了.被装载到内存中去了.(你的代码保存在磁盘上没装入内存之前是个死家伙.只有跑到内存中才变成活的).而运行时类型检查就与前面讲的编译时类型检查(或者静态类型检查)不一样.不是简单的扫描代码.而是在内存中做些操作,做些判断.

    相关问题整理

    1、为什么OC不能sizeof一个对象的大小?和类结构相近的结构体却可以

    因为oc的动态继承编译机制,动态继承机制,就是说在编译的时候不能确定父类的大小,只有在运行时才能确定父类大小,
    sizeo是在栈中操作的,编译的时候就会计算出来sizeof的值

    而栈中不知道对象的父类大小,所以不能使使用sizeof计算出对象的大小

    2、为什么OC不能将对象声明到静态空间,如栈中,和类相近的结构体却可以

    栈是在编译完成后产生的,编译的结果是二进制机器文件,即汇编栈已经产生,所以栈内不能放类的对象,因为产生栈的时候不知道父类的大小

    栈是由汇编代码指令描述的
    为什么结构体可以直接寄计算sizeof,也能直接声明到静态空间呢?
    为什么结构体不管定义在栈中或堆中都能直接sizeof?因为定义到堆中的时候已经知道了结构体的大小,因为结构体对于调用它的代码产生的栈而言是暴露的。
    是因为结构体定义的头文件直接把结构体的属性暴露给了栈,所以可以直接声明到静态空间
    总之一句话,父类的详细情况对于调用其子类的栈来说是封闭的,而结构体相对于调用它的栈来说是暴露的。

    OC中的动态继承编译机制是在编译的时候不把父类详细情况暴露给调用子类的栈,而是在运行的时候才把父类的详细情况暴露给调用子类的栈

    更多iOS 开发相关知识

    我的简书主页

    相关文章

      网友评论

          本文标题:iOS 扩展(Extension)以及和类别(Category)

          本文链接:https://www.haomeiwen.com/subject/nbimactx.html