美文网首页将来跳槽用
重学iOS——6.类工厂方法注意点以及id和instancety

重学iOS——6.类工厂方法注意点以及id和instancety

作者: Peak_One | 来源:发表于2017-11-01 16:23 被阅读66次
    类工厂方法的注意点

    类工厂方法是一种用于分配、初始化实例并返回一个它自己的实例的类方法。类工厂方法很方便,因为它们允许您只使用一个步骤(而不需要多余的代码)就能创建对象,例如:new.

    自定义类工厂方法的规范:

    • 一定是+号开头的类方法
    • 返回值一般是instancetype或者id类型
    • 方法名称以类名开头,首字母小写
    +(id)person;
    +(id)person
    {
        return [[Person alloc]init];
    }
    
    +(instancetype)personWithAge:(int)age;
    +(instancetype)personWithAge:(int)age
    {
        Person *p=[[Person alloc]init];
        p.age=age;
        return p;
    }
    

    但是在继承的过程中会出现一些问题,问题如下代码所示:
    父类Person 子类Student

    -------------------------Person.h-------------------------
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    @property int age;
    +(instancetype)person;
    @end
    
    
    -------------------------Person.m-------------------------\
    #import "Person.h"
    
    @implementation Person
    
    +(instancetype)person
    {
        
        /*
         * 注意:以后凡是自定义类工厂方法,在类工厂方法中创建对象一定不要使用类名来创建,一定要使用self来创建
         * self在类方法中就代表类对象,到底代表哪一个类对象?谁调用当前类方法,self就代表谁
         * 这样就可以避免类工厂方法在继承过程中出现的给对象发送未知方法的问题
         */
        return [[Person alloc]init];
    }
    
    @end
    
    -------------------------Student.h-------------------------
    #import "Person.h"
    
    @interface Student : Person
    
    @property int no;
    @end
    
    
    -------------------------Student.m-------------------------
    #import "Student.h"
    
    @implementation Student
    
    @end
    

    在main方法中的代码如下:

    #import <Foundation/Foundation.h>
    #import "Student.h"
    int main(int argc, const char * argv[]) {
        Student *stu=[Student person];
        NSLog(@"%i",stu.age); 
        stu.no=111;
        return 0;
    }
    

    结果运行以后,会出现如下的错误信息!

    报错信息.png

    这就是运行时错误,虽然Student类继承自Person,调用Person的类工厂方法,但是方法内部创建的是一个Person对象,也就是说此时的stu对象实质上是一个Person对象,所以才会报找不到方法的错误。
    所以在使用过程中,为了能够使继承到的类工厂方法不影响使用,我们一般采用self关键字,进行定义,具体改良办法如下:

    -------------------------Person.h-------------------------
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    @property int age;
    +(instancetype)person;
    @end
    
    
    -------------------------Person.m-------------------------\
    #import "Person.h"
    
    @implementation Person
    
    +(instancetype)person
    {
        
        /*
         * 注意:以后凡是自定义类工厂方法,在类工厂方法中创建对象一定不要使用类名来创建,一定要使用self来创建
         * self在类方法中就代表类对象,到底代表哪一个类对象?谁调用当前类方法,self就代表谁
         * 这样就可以避免类工厂方法在继承过程中出现的给对象发送未知方法的问题
         */
        return [[self alloc]init];
    }
    
    @end
    

    此时再去调用person方法,就不会报错了,谁调用,这个self就指向哪个类。

    id和instancetype的区别

    instancetype和id:instancetype==id==万能指针==指向一个对象
    但是instancetype是对id的改良,是为了避免使用id出现运行时错误才引进的,目的是将运行时错误,在编译时展示给开发人员。

    1. 如果init方法的返回值是instancetype,那么将返回值复制给一个其他的对象会报一个警告
    2. 如果是在以前,init的返回值是id,那么将init返回的对象地址赋值给其他对象是不会报错的
    3. id在编译的时候,不会判断对象的真实类型,而instancetype会在编译时判断对象的真实类型
    4. instancetype是Apple官方将运行时错误展示到编译时
    5. id和instancetype除了一个在编译时不知道真实类型,一个在编译时知道真实类型以外,还有另外一个区别
    6. instancetype只能用于作为函数的返回值,id可以用来定义变量,可以作为返回值,可以作为形参
    7. 注意:以后但凡自定义构造方法,返回值尽量使用instancetype,不要使用id

    欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!


    0.jpg

    相关文章

      网友评论

        本文标题:重学iOS——6.类工厂方法注意点以及id和instancety

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