书接上文。
这次研究下oc中继承与java中的区别。
其实区别就是,基本上没有任何区别。在概念上而言,类分为两种,根类和子类,所有根类都是整个类结构中最上层的那个类,也可称之为祖父类,继承祖父类的类都可以叫做子类,不过仅仅是相对于根类而言,换句话说,所有的类之间的关系都是相对而言。而所谓的继承就相当于遗产,只不过这些遗产被抽象成定义的变量和方法而已。你可以从你的父亲哪里继承遗产,同样,你父亲也从你祖父那里继承遗产,而你从父亲那里继承的遗产,很有可能绝大部分是你父亲从你祖父那里继承过来的,也就是说,你继承过来的遗产中,同时包含了你父亲和你祖父的遗产。
在oc中同样可以这样理解,当ClassA中继承ClassB 中的方法和变量,ClassB从NSobject中继承了 NSobject中的所有变量和方法,那么ClassA 中也同样又NSobject中的所有变量和方法。
但是继承是一个单方向的操作,不管你从继承中学会了多少变量和方法,你可以选择不用,但是他一直就在那里。如果需要对继承过来的方法进行修改,就需要用到重载的概念。所谓重载,就是在子类中重新定义从父类中继承过来的方法。当然你也可以选择增加新的变量。但是重载的方法必须形式上同继承的方法一模一样,有相同的返回值和相同的参数。如果你使用不同的返回值或者不同的传入参数或者两者都不同,那么就不是继承了,就变成多态了。
下面附上《objective-c 程序设计(第二版)》中关于继承的例子:
XYpoint.h
//
// Rectangle.h
// chapter-8
//
// Created by 石林
// Copyright 2011年
//
#import <Foundation/Foundation.h>
#import "XYpoint.h"
@interface Rectangle : NSObject
int
int
XYpoint
}
@property int
-(XYpoint
-(void) setOrigin:(XYpoint
-(void) setWidth:(int) w andHeight:(int) h;
-(int) area;
-(int) perimeter;
@end
XYpoint.m
//
// XYpoint.m
// chapter-8
//
// Created by 石林
// Copyright 2011年
//
#import "XYpoint.h"
@implementation XYpoint
@synthesize x,y;
-(void)setX:(int)xVal andY:(int)yVal
{
x=xVal;
y=yVal;
}
@end
//
// Rectangle.h
// chapter-8
//
// Created by 石林
// Copyright 2011年
//
#import <Foundation/Foundation.h>
#import "XYpoint.h"
@interface Rectangle : NSObject
int
int
XYpoint
}
@property int
-(XYpoint
-(void) setOrigin:(XYpoint
-(void) setWidth:(int) w andHeight:(int) h;
-(int) area;
-(int) perimeter;
@end
//
// Rectangle.m
// chapter-8
//
// Created by 石林
// Copyright 2011年
//
#import "Rectangle.h"
@implementation Rectangle
@synthesize
-(XYpoint
{
return origin;
}
-(void) setOrigin:(XYpoint
{
origin=pt;
//origin=[[XYpoint alloc] init];
//[origin setX:pt.x andY:pt.y];
}
-(void) setWidth:(int)w andHeight:(int)h
{
width=w;
height=h;
}
-(int) area
{
return width*height;
}
-(int) perimeter
{
return (width+height)*2;
}
@end
//
// main.m
// chapter-8
//
// Created by 石林
// Copyright 2011年
//
#import <Foundation/Foundation.h>
#import "XYpoint.h"
#import "Rectangle.h"
int main (int argc, const char
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
XYpoint *myPoint=[[XYpoint alloc] init];
Rectangle *myRectan=[[Rectangle alloc] init];
setX:1000 andY:2000];
setWidth:100 andHeight:200];
myRectan.origin=myPoint;
NSLog(@"%i,%i",myRectan.width,myRectan.height);
NSLog(@"%i,%i",myRectan.origin.x,myRectan.origin.y);
setX:90 andY:80];
myRectan.origin=myPoint;
NSLog(@"%i,%i",myRectan.origin.x,myRectan.origin.y);
NSLog(@"%i",myRectan.area);
NSLog(@"%i",myRectan.perimeter);
release];
release];
drain];
return 0;
}
本书中使用这个例子,其实是为了说明一个关于穿参数的问题。
我再main文件中对例子做了一点修改,书上在Rectangle.h文件中加入了两行代码,实现在修改XYpoint值之后同样可以保证Rectangle中的xypoint值发生改变。书上的做法是将传入origin实例后再次实例化一个对象,这样每次更改以后都是使用新的更改以后的对象,从而实现更改以后参数发生改变。
但是其实,再次使用myRectan.origin=myPoint,一样可以达到这个效果,只不过在每次修改以后再次将mypoint的值传入origin中,让指针的位置发生改变。同样可以解决这个问题。
这样修改的好处在于,不用释放[myRectan origin]中实例化出来的对象。直接使用[myRectan release]就能释放所有的myrectan占用的内存。
既然说到了重载,就不得说一下使用教程中的方法进行修改后如何释放内存,教程中释放内存的思路是这样的,在使用[myRectan release]的时候,是不会释放这个类中继承的类的内存,所以我们要重写dealloc方法。
-(void) dealloc
{
if(origin)
{
[origin release];
[super dealloc];
}
}
这样就能释放origin的内存,然后通过super关键字向上查询,直到释放完所有的继承的类的内存为止。