zoukankan      html  css  js  c++  java
  • 1.5 万能指针 id

    一. id

    id是一种数据类型,并且是一种动态数据类型

    数据类型的用途:

    1. 定义变量

    2. 作为函数的参数

    3. 作为函数的返回值

    默认情况下所有的数据类型都是静态数据类型

    静态数据类型的特点:

    在编译时就知道变量的类型,知道变量中有哪些属性和方法

    在编译的时候就可以访问这些属性和方法

    并且如果是通过静态数据类型定义变量,如果访问了不属于静态数据类型的属性和方法,那么编译器就会报错

    应用场景:多态,可以减少代码量,避免调用了子类特有的方法需要强制类型转换

    1. id obj1 =[[Person alloc] init];
    2. [obj1 sleep];
    3. [obj1 test];// Person类的私有方法
    4. id obj2 =[[Person alloc] init];
    5. [obj2 eat];
    6. [obj2 test];// Person类的私有方法

    为了避免动态数据类型引发的运行时的错误,一般情况下如果使用动态数据类型定义一个变量,在调用这个对象的方法之前会 进行一次判断,判断当前对象是否能够调用这个方法

    1. 判断指定的对象是否是某一个类,或者是某一个类的子类

    1. id obj =[[Student alloc] init];
    2. if(obj isKindOfClass:[Studentclass]){
    3. // 如果obj对象是Student类创建出来的或者是Student的子类创建出来的对象调用父类的eat方法
    4.   [obj eat];
    5. }

    2. 判断指定的对象是否是当前指定的类的实例

    1. id obj =[[Student alloc] init];
    2. if(obj isMemberOfClass:[Studentclass]){  
    3.   // 判断对象obj是否是Student类创建出来的对象,如果是调用类的对象方法    
    4.   [obj eat];
    5. }

    二. new的实现原理

    1. 创建对象new做了三件事情:

    1>. 开辟存储空间  + alloc 方法;

    2>. 初始化所有的属性(成员变量) - init 方法;

    3>. 返回对象的地址

    2. + alloc做了什么事情

    1>. 开辟存储空间;

    2>. 将所有的属性设置为0;

    3>. 返回当前实例对象的地址

    1. Person*p1 =[Person alloc];

    3. - init做了什么事情

    1>. 初始化成员变量,但默认情况下init的实现是什么都没有做;

    2>. 返回初始化后的实例对象的地址

    1. Person*p2 =[p1 init];
    注: + alloc 和 - init 返回的实例对象的地址是同一个地址

    三. 构造方法

    在OC中init开头的方法,我们称之为构造方法

    构造方法的用途: 用于初始化一个对象,让某个对象一创建出来就拥有某些属性和值

    1. 重写init方法,在init 方法中初始化成员变量

    1>. 必须先初始化父类,再初始化子类

    2>. 必须判断父类是否初始化成功,只有父类初始化成功才能继续初始化子类

    3>. 返回当前对象的地址

    1. - instancetype init
    2. {
    3.   if(self =[super init]){
    4.       _age =10;
    5.   }
    6.   return self;
    7. }

    2. instancetyp和id的区别

    instancetype == id == 万能指针 == 指向一个对象

    id 在编译的时候不能判断对象的真实类型

    instancetype 在编译的时候可以判断对象的真实类型

    1>. id和instancetype除了一个在编译时不知道真实类型,一个在编译时知道真实类型

    2>. id可以用来定义变量,可以作为返回值,可以作为形参,instancetype只能作为返回值

    注:以后但凡自定义构造方法,返回值尽量使用instancetype,不要使用id

    3. 自定义构造方法 (init自定义构造只用初始化自己的成员变量,父类的父类来处理)

    1. -(instacetype)initWithAge:(int)age andName:(NSString*)name
    2. {
    3.   if(self =[super init]){
    4.     _age = age;
    5.     _name = name;
    6.   }
    7.   return self;
    8. }
      // NSLog输出%@ 最好重写 - (NSString *)description;
    1. -(NSString*)description
    2. {
    3.   return[NSString stringWithFormat:@"age = %i, name = %@", _age, _name];
    4. }

    4. 自定义类工厂方法

    1> 类构造方法:initWith.....

    1. -(instancetype)initWithAge:(int)age andName:(NSString*)name
    2. {
    3.   if(self =[super init]){
    4.     _age = age;
    5.     _name = name;
    6.   }
    7.   return self;
    8. }
    2> 类工厂方法:类名开头.....
    1. +(instancetype)personWithAge:(int)age
    2. {
    3.    Person*p =[[self alloc] init];
    4.    p.age = age;
    5.    return p;
    6. }
    四. 类的本质

    五.SEL类型

    1.创建一个人对象

    1. Person*p =[[Person alloc] init];

    2.agesetter方法封装成SEL

    1. BOOL b =[p respondsToSelector:sel];
    2. NSLog(@"%i", b);

    3.判断Person对象方法中中是否存在 - 号开头的setAge:方法

     

    1. BOOL b =[p respondsToSelector:sel];
    2. NSLog(@"%i", b);
    4.判断Person类方法中是否存在 + 号开头的setAge:方法
    1. b =[Person respondsToSelector:sel];
    2. NSLog(@"%i", b);

    5.通过performSelector调用有参数的方法, 那么参数必须是对象类型

    1. SEL sel1 =@selector(setName:);
    2.        
    3. [p performSelector:sel1 withObject:@"jack"];
    4. NSLog(@"name = %@", p.name);
     





  • 相关阅读:
    Android Studio 快捷键
    Mac 下面,添加android adb命令(一般环境变量的添加方法)
    快速掌握 Android Studio 中 Gradle 的使用方法
    JAVA 十六进制与字符串的转换
    总结自己的Git常用命令
    Android性能优化典范---转
    【.NET Core微服务实战-统一身份认证】开篇及目录索引
    调用API修改Ocelot的配置文件
    VUE组件汇总
    Vue + GraphQL初试
  • 原文地址:https://www.cnblogs.com/Xfsrn/p/4780784.html
Copyright © 2011-2022 走看看