书接上文。

这次研究下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关键字向上查询,直到释放完所有的继承的类的内存为止。