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

 

大家可以一起学习ios,每天学习一点点,让自己的知识面更广,日积月累。...



前言


这本书已经看完了,但是现在有个感觉是:看了后面的知识,前面看过的知识就忘记了,并且自己对整个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新手,文章如有不对的地方,欢迎大家多多指正。


    关注 AndroidIosRN程序员


微信扫一扫关注公众号

0 个评论

要回复文章请先登录注册