前言
<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
本人公众账号
网友评论