OC语言-特有语法
OC语言-特有语法
盘盘的灰灰 发表于2年前
OC语言-特有语法
  • 发表于 2年前
  • 阅读 6
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   

 

  • 结构体与类的不同点

        1). 结构体只能封装数据,而类不仅可以封装数据还可以封装行为.

        2). 结构体变量分配在栈空间 (如果是1个局部变量的情况下)

            而对象分配在堆空间.

            栈的特点: 空间相对较小. 但是存储在栈中的数据访问的效率更高一些.

            堆的特点: 空间相对较大. 但是存储在堆中的数据访问的效率相对要低

            存储在栈中的数据访问效率高 存储在堆中的数据访问效率低.

        3). 赋值.

            结构体 Student

            类:   Person

            Student s1 = {"jack",19,GenderMale};

            Student s2 = s1;

            Person *p1 = [Person new];

            Person *p2 = p1;

  • 讨论三个问题

         1). 类什么时候加载到代码段.

             类第1次被访问的时候,类就会被加载到代码段存储 类加载.

         2). 类以什么样的形式存储在代码段.

         3). 类一旦被加载到代码段之后 什么时候回收.

             是不会被回收的 除非程序结束.

  • 在代码段存储类的那块空间是个什么类型的.

             在代码段中存储类的步骤

             a. 先在代码段中创建1个Class对象, Class是Foundation框架中的1个类.

                这个Class对象就是用来存储类信息的.

             b. 将类的信息存储在这个Class对象之中.

                这个Class对象.至少有3个属性

                类名: 存储的这个类的名称.

                属性s: 存储的这个类具有哪些属性

                方法s: 存储的这个类具有哪些方法.

             所以.类是以Class对象的形式存储在代码段的.

             存储类的这个Class对象 我们也叫做类对象. 用来存储类的1个对象.

             所以,存储类的类对象也有1个叫做isa指针的属性 这个指针指向存储父类的类对象. 

  •   SEL其实是1个类. SEL对象是用来存储1个方法的.

    类是以Class对象的形式存储在代码段之中.

     类名:存储的这个类的类名. NSString 

     还要将方法存储在类对象之中.如何将方法存储在类对象之中.

     1). 先创建1个SEL对象.

     2). 将方法的信息存储在这个SEL对象之中.

     3). 再将这个SEL对象作为类对象的属性.

 

  • 调用方法的本质.

      [p1 sayHi];

      内部的原理:

      1). 先拿到存储sayHi方法的SEL对象,也就是拿到存储sayHi方法的SEL数据. SEL消息.

      2). 将这个SEL消息发送给p1对象.

      3). 这个时候,p1对象接收到这个SEL消息以后 就知道要调用方法

      4). 根据对象的isa指针找到存储类的类对象.

      5). 找到这个类对象以后 在这个类对象中去搜寻是否有和传入的SEL数据相匹配的.

          如果有 就执行  如果没有再找父类 直到NSObject

 

      OC最重要的1个机制:消息机制.

      调用方法的本质其实就是为对象发送SEL消息.

      [p1 sayHi]; 为p1对象发送1条sayHi消息.

  • 点语法的原理.

        p1.age = 18;

        这句话的本质并不是把18直接赋值给p1对象的_age属性.

        点语法在编译器编译的时候.其实会将点语法转换为调用setter、getter的代码.

     

  •  使用@property注意.

         1). @property的类型和属性的类型一致.

             @property的名称和属性的名称一致(去掉下划线)

             不要乱写.

         2). @property的名称决定了生成的getter和setter方法的名称.

               所以,@property的名称要和属性的名称一致 去掉下划线  否则生成的方法名就是不符合规范的

             @property的数据类型决定了生成的setter方法的参数类型 和 getter方法的返回值类型.

         3). @property只是生成getter和setter方法的声明. 实现还要自己来. 属性还要自己定义.

  • @synthesize

         1).作用: 自动生成getter、setter方法的实现.

                 所以,应该写在类的实现之中.

    注意:

        1). 如果直接写1个@synthesize

            @synthesize name;

        2). 如果指定操作的属性.

            @synthesize name = _name;

        3). 生成的setter方法实现中 是没有做任何逻辑验证的 是直接赋值.

            生成的getter方法的实现中 是直接返回属性的值.

             如果setter或者getter有自己的逻辑验证 那么就自己在类的实现中重写就可以了. 

  • 静态类型:

         指的是1个指针指向的对象是1个本类对象.

         动态类型:

         指的是1个指针指向的对象不是本类对象.

  •  id指针.

         是1个万能指针,可以指向任意的OC对象.

         1). id是1个typedef自定义类型 在定义的时候已经加了*

             所以,声明id指针的时候不需要再加*了.

  • NSObject和id的异同.

         相同点: 万能指针 都可以执行任意的OC对象.

         不同点: 通过NSObject指针去调用对象的方法的时候.编译器会做编译检查.

                通过id类型的指针去调用对象的方法的时候,编译器直接通过.无论你调用什么方法. 

         注意: id指针只能调用对象的方法  不能使用点语法.如果使用点语法就会直接报编译错误 。

         如果我们要声明1个万能指针 千万不要使用NSObject 而是使用id 

  • id和instancetype的区别.

             1).instancetype只能作为方法的返回值.不能在别的地方使用.

                id既可以声明指针变量 也可以作为参数 也可以作为返回值.

             2). instancetype 是1个有类型的 代表当前类的对象.

                id是1个无类型的指针 仅仅是1个地址.没有类型的指针. 

  • 判断对象中是否有这个方法可以执行.

         - (BOOL)respondsToSelector:(SEL)aSelector;

        判断类中是否有指定的类方法.

         + (BOOL)instancesRespondToSelector:(SEL)aSelector;

        判断指定的对象是否为 指定类的对象或者子类对象.

        - (BOOL)isKindOfClass:(Class)aClass;

        判断对象是否为指定类的对象 不包括子类.

         - (BOOL)isMemberOfClass:(Class)aClass;

        判断类是否为另外1个类的子类.

        + (BOOL)isSubclassOfClass:(Class)aClass;

  •  类名 *指针名 =  [类名  new];

             new实际上是1个类方法.

            new方法的内部,其实是先调用的alloc方法. 再调用的init方法.

     alloc方法是1个类方法,作用: 那1个类调用这个方法 就创建那个类的对象,并把对象返回.

     init方法 是1个对象方法,作用: 初始化对象.

    

创建对象的完整步骤:

     应该是先使用alloc创建1个对象,然后再使用init初始化这个对象 才可以使用这个对象.

     虽然没有初始化的对象 有的时候 也可以使用. 但是千万不要这么做.

     使用1个未经初始化的对象是极其危险的.

     Person *p1 = [Person new];

     完全等价于

     Person *p1 = [[Person alloc] init];

  • init方法.

         作用: 初始化对象,为对象的属性赋初始值 这个init方法我们叫做构造方法.

  • 重写init方法的规范:

         1). 必须要先调用父类的init方法.然后将方法的返回值赋值给self

         2). 调用init方法初始化对象有可能会失败,如果初始化失败.返回的就是nil

         3). 判断父类是否初始化成功. 判断self的值是否为nil 如果不为nil说明初始化成功.

         4). 如果初始化成功 就初始化当前对象的属性.

         5). 最后 返回self的值.

  • 重写init方法的规范.

         - (instancetype)init

         {

             if(self = [super init])

             {

                //初始化当前类的属性的代码;

             }

             retrun self;

         }

         什么时候需要重写init方法:

         如果你希望创建出来的对象的属性的默认值不是 nil NULL 0 而是我们指定的值.

         那么这个时候我们就可以重写init方法.

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 0
博文 31
码字总数 24142
×
盘盘的灰灰
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: