"OC基础"这个分类的文章是我在自学Stephen G.Kochan的《Objective-C程序设计第6版》过程中的笔记。
1、根类即是最顶层的类,父类也可称为超类;
2、关于实例变量的继承:
只有声明在@interface部分的实例变量才能被子类继承:包括在类名后马上使用花括号声明的变量和使用@property声明的变量,都可以继承。如果完全声明在@implementation部分的变量,则属于私有变量,需要提供方法才能访问。
3、每个实例都有自己的一套实例变量,即使这套实例变量是继承来的。比如bClass是从aClass继承来的,他们都有一个变量(int) n,那么当改变了aClass.a的值的时候,bClass.a的值不会随着改变。他们是两个不同的实例。
反观另一种特别的情况(代码8-5):Rectangle类是矩形类,XYPoint类是点类,Rectangle类里面包含了一个变量origin是(XYPoint *)类型的,用来存放这个矩形的位置点。新建了一个Rectangle类的实例myRect,新建了一个XYPoint类的实例myPoint,然后通过语句
myRect.origin= myPoint;
将myPoint的值赋给myRect作为它的位置点。这时候出现了一种情况,当myPoint的值改变了以后,myRect所包含的origin变量的值也跟着改变了。原因是使用上面的语句的时候,赋给origin变量的值并不是myPoint的内容,而是一个指针,指向了myPoint的存储位置,所以当myPoint的内容改变了以后,origin变量的值也跟着改变了,myRect并没有自己新建一套变量去存储myPoint的内容,存放的仅仅是一个指针。
对于这两种情况要区别去理解:aClass和bClass是两个不同的实例,各有各的变量;myRect并没有用一个变量去存储myPoint的内容,仅仅只用了一个(XYPoint *)类型的变量来存放了myPoint的指针。
4、对于3中的myRect和myPoint,只要在myRect里面重新声明了myPoint用以存放位置的几个变量,然后把myPoint里面对应的变量值一一赋给自己的变量,那么myPoint的值再怎么改变也不会再影响到myRect包含的位置点变量了。其实即是在myRect的内部声明一个myPoint,即有了一个私有的myPoint。
5、关于@class指令,比如在接口文件CClass.h中有如下代码段:
#import <Foundation/Foundation.h>
@class AClass
@interfaceCClass: NSObject
…
在这段代码中出现了指令@class,它的意思是接下来的代码中会使用到AClass这个类,这里告诉编译器接下来如果遇到“AClass”就把它当做一个类来对待即可。
但是如果下方代码要访问到Aclass包含的变量,那就会报错,这种情况应该把Aclass.h这个接口文件import进来。
6、关于4,其实不用再去声明XYPoint类的变量,只需要将Rectangle类中设置origin的方法改写如下即可:
-(void)setOrigin: (XYPoint *) pt {
if (! origin) { //如果origin是空的,则为false,那么(! origin)为true,执行以下代码;
origin = [[XYPoint alloc] init];
}
origin.x = pt.x; //x和y都是XYPoint的变量,这里origin是一个(XYPoint *)型的变量,
origin.y = pt.y; //它也会包含有一套xy,所以不需再去声明一套;
}
直接在方法中设置一套xy,就不会受myPoint影响。
这种情况下,虽然origin.x被赋予的仍然是pt.x的指针,但是也完全不需要担心会受到myPoint的影响的了,因为虽然现在origin.x和pt.x指向的是同一块内存,但是如果改变了pt.x的值的话,其实系统是新分配了一块内存写了一个新的值,然后让pt.x指向这块新的内存,origin.x指向的内存不会受到任何影响。
以下图为例:
(1)、origin = myPoint是这种情况:
(2)、origin.x = pt.x是这种情况:
7、在默认的情况下,合成(synthesize)的设值方法只是简单地复制对象的指针,而不是对象的本身,其实即是assign。
8、关于方法的覆写:
覆写的方法是一个同名的新方法,必须有相同的返回类型,并且参数的数目也不能改变。