学习ios之路:objective-c--实例变量总结

作者: 牛晓伟 | 来源:发表于2016-05-05 08:02 被阅读1746次
    201-5-730x456.jpg

    前言


    <Programming in Objective-c2.0>这本书已经看完了,但是现在有个感觉是:看了后面的知识,前面看过的知识就忘记了,并且自己对整个oc的知识体系没有一个系统的认识。因此计划在重新复习下。

    因为java和oc都是面向对象的语言,所以说到底它们都有面向对象的三大特性:封装,继承,多态。因此我觉得可以根据我对java的掌握,来帮助自己复习oc,于是乎自己总结了一个java的知识体系,根据该知识体系可以复习oc。

    关于oc中的各种运算符,基本类型等知识基本和java中一样,所以就没必要复习了。不管是java中还是oc中,一个类包含:属性+操作两部分,因此先从属性(此处的属性不是oc中的通过@property声明的属性)部分开始复习。谈到属性那就会谈到各种变量,先看下都有哪些变量。

    这几篇系列文章我将复习oc中的各种变量

    • 实例变量
    • 静态变量
    • 常量
    • 全局变量
    • 局部变量

    先开始实例变量的复习

    oc中的实例变量


    实例变量是什么就不需要多讲了,首先我们从过时的声明实例变量语法开始本篇内容

    过时的声明实例变量语法


    以下声明实例变量的语法已经过时,但是我们有必要熟悉下

            访问权限  类型  变量名;  //声明一个实例变量
    

    如上语法,访问权限有(@public, @package, @protected, @private 它们和java中的访问权限基本是一样的)。
    若访问权限为@private,则该实例变量是私有的,只能被本类使用
    在声明实例变量时,不加访问权限,该实例变量的访问权限是@protected,该实例变量可以被子类继承。
    若访问权限是@public,则其他类可以使用该实例变量.

    声明类类型的变量如下

        NSString * name;//声明一个访问权限为@protected类型为NSString的对象
    

    类类型变量,变量名之前必须加"*",可以理解为引用。

    声明基本类型的变量如下

        @private int age;//声明一个私有的int类型的变量
    

    应该在类的什么位置声明实例变量呢?
    首先声明的实例变量要被放在一对"{}"中,如下

        {
              NSString *name;
        }
    

    那"{}"应该放在什么位置,大家肯定会说放在类里面,因为oc中的类分为2部门:类声明部分(头文件)和类实现部分(.m文件),那到底应该放在类声明部分里还是类实现部分里呢,那我们仔细来分析下:

    放在类声明部分(@interface @end之间),如下

      @interface ClassName : ParentName{
            在此肆意的声明实例变量
      }
      @end
    

    放在类的实现部分(@implementation @end之间),如下

      @implementation ClassName{
            在此也可以声明实例变量
      }
      @end
    

    并且还可以放在extension(extension是新版oc推出的特性),如下

      @interface ClassName() {
                        在此也可以声明实例变量
    
      }
      @end
    

    那我们来对比下:

    • 实例变量在类的声明处声明,若它的访问权限不是@private,那它是可以被子类继承的,并且可以被其他类访问(若访问权限是@public)

    • 实例变量在类的实现处声明和在extension中声明,该实例变量是私有的,即使加@public访问权限也是私有的,不可以被子类继承

    虽然这种声明实例变量的语法已经过时了,但是我们有必要了解。

    实例变量的访问


    本类中的实例方法访问自己的实例变量:

        instanceVar //直接使用
        self->instanceVar//通过self->来使用,不推荐这种使用方式
    

    其他类中访问一个类的实例变量(前提该类的实例变量是可以被访问的)

        self->instanceVar //这种破坏了类数据的封装性,所以一般是不会把类的实例变量暴漏给其他类的
    

    过时的实例变量的存取器语法


    存取器也就是getter/setter方法,oc中我们可以不需要手动编写存取器代码,利用一些指令让编译器自动生成存取器代码。在较老的OC版本中,语法是这样的

        //ClassName.h文件中(类声明文件中)
        @interface ClassName: NSObject{
              //声明_ivar实例变量
              NSString * _ivar;
        }
        //为_ivar实例变量声明getter/setter方法
        @property (nonatomic,copy)  NSString * ivar;
        @end
    
    
        //ClassName.m(类实现文件)
        @implementation ClassName
        //实现_ivar实例变量的getter/setter方法
        @synthesize ivar = _ivar;
        @end
    

    以上代码定义了一个_ivar的实例变量,同时为_ivar变量定义了getter/setter方法,那我们看看是怎么做到的:

    第一步:声明一个实例变量

         @interface ClassName: NSObject{
              NSString * _ivar;
         }
    

    第二步:声明一个属性:

         @property (nonatomic,copy)  NSString * ivar;
    

    以@property指令开头的代码,声明了一个ivar的属性,该属性的主要作用是告诉编译器帮我生成声明ivar/setIvar方法的代码,生成的代码如下面

        - (void) setIvar:(NSString *) ivar;
        - (NSString *) ivar;
    

    @property指令其实就是省的我们自己在手动写这些getter/setter的声明了,属性声明的语法是:

        @property (参数1,参数2) 类型 propertyName
    
        其中参数主要分为三类:
         读写属性: (readwrite/readonly)
         setter语意:(assign/retain/copy)
         原子性: (atomicity/nonatomic)
         参数类型放在后面在复习
    

    第三步:实现getter/setter方法
    @synthesize是对通过@property声明的getter/setter方法进行实现。它的语法是:

        @synthesize propertyName = ivar;
    

    @synthesize后面的propertyName是@property声明的属性的名字,"= ivar"意思是指定给哪个实例变量生成getter/setter方法,是可以省略的(前提条件是propertyName与其中一个实例变量的名字相同,类型也得一样,但是这种实例变量名字与getter方法名字相同的情况官方是不建议使用的,因为这有可能会引入错误)

    以上的生成实例变量的存取器的方法已经过时了,并且比较繁琐,所以我们来看下新的方式。

    新时代声明实例变量,实例变量存取器实现语法


    既然本文章刚开始就提到过时的声明实例变量的语法,过时的实例变量存取器语法,那我们就来看下全新的语法到底是什么样的,到底带来哪些便利。
    直接看语法:

        //ClassName.h文件中(类声明文件中)
        @interface ClassName: NSObject{
        
        //只需要定义一个属性即可搞定 声明实例变量,为实例变量生成存取器方法
        @property (nonatomic,copy)  NSString * ivar;
        @end
    

    新的语法其实就是把声明实例变量@synthesize语句去掉了,这些代码可以由编译系统生成。这种方法是不是特别简单啊,只需通过@property指令定义一个属性,该属性就会告诉编译器,把声明实例变量以及实例变量的存取器方法都给自动生成。声明的实例变量的名字是 由 "_"+属性名字组成的(_propertyname)。声明的语法是:

      @property (参数1,参数2) 类型 propertyName
    

    通过属性来声明实例变量是新版oc中强烈建议的

    调用通过属性生成的存取器


    分两种情况:在本类中和在其他类中
    1.在本类中
    语法格式是:

      self.propertyName
    

    该语法可以调用存取器,但具体调用的是getter还是setter方法呢?这就得由self.propertyName处于"="(赋值符)的左边还是右边来决定。
    self.propertyName处于左边,调用的是setter方法

        self.propertyName = newValue //调用的是属性对应的实例变量的setter方法
    

    self.propertyName处于右边,调用的是getter方法

        value = self.propertyName  //调用的是属性对应的实例变量的getter方法
    

    还可以使用下面的语法,但是既然有上面语法这么简单就没必要使用下面的语法了

      [self setPropertyName: value];
      value = [self getProperty];
    

    2.在其他类中
    把第一种情况的self换为相应的类实例即可,比如

      ClassA  * classA;
      classA.propertyName;
    

    实现属性声明的实例变量的继承


    通过声明属性的方式声明的实例变量的访问权限是@private,所以子类是不能继承该实例变量的。若想实现继承由属性方式声明的实例变量,可以手动声明实例变量,声明的实例变量的名字格式是

        _propertyName
    

    比如:

      @property NSString *name;
    

    则手动声明实例变量代码是:

      NSString * _name;
    

    这样就可以让通过属性声明的实例变量被子类继承。

    @property指令在以下2处是可以使用的

    • 类的声明处(@interface @end之间),在本处声明的属性,该属性对应的存取器是可以被其他类使用的,该属性对应的实例变量是私有的
    • 类的extension处(@interface() @end之间),在本处声明的属性,该属性对应的存取器是私有的,属性对应的实例变量肯定更是私有的

    @property指令在以下2处不可以使用

    • 类的实现处(@implementation @end之间),使用会报错
    • 类的分类(category),类的分类不可以声明实例变量

    总结


    通过本篇我复习了

    • 过时的声明实例变量语法,虽然过时但是有必要了解
    • 实例变量的访问(在本类中和在其他类中访问实例变量的语法)
    • 过时的实例变量存取器语法
    • 新时代的实例变量声明,实例变量存取器实现的语法
    • @property指令声明的属性的使用方式

    我是oc新手,文章如有不对的地方,欢迎大家多多指正。

    本人微信:704451290

    本人公众账号

    相关文章

      网友评论

      • zziazm:"实例变量在类的声明处声明,若它的访问权限不是@private,那它是可以被子类继承的,并且可以被其他类访问(若访问权限是@public)"我试了下,@package的权限也可以被其他类访问
      • 黑白咖:跳过
      • 西叶lv:通过声明属性的方式声明的实例变量的访问权限是@private,所以子类是不能继承该实例变量的。???这边有些问题!!!在类的声明处(@interface @end之间)的属性,不是私有类的,可以被子类继承……还有OC的变量和方法,怎么自己设置访问权限???楼主知道么?
      • 45c4bd1cc318:我也是从android转来的,也有同样的问题,谢谢分享
      • 小明同学:LZ 为什么不直接学习 Swift ?
        AnLuoRidge:@小明同学 业界并未大规模使用Swift
      • 因幡白兔:加油!
      • 子茗:占位支持!

      本文标题:学习ios之路:objective-c--实例变量总结

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