技术iOS 易混淆的点首页投稿(暂停使用,暂停投稿)

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

2016-05-05  本文已影响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

那我们来对比下:

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

实例变量的访问


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

    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处是可以使用的

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

总结


通过本篇我复习了

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

本人微信:704451290

本人公众账号
上一篇下一篇

猜你喜欢

热点阅读