您的位置:首页 > 移动开发 > Objective-C

黑马程序员 — Objective-C学习笔记(二):继承

2015-03-28 05:12 309 查看
——- android培训IOS培训、期待与您交流! ———-

继承

使用继承可以定义一个具有父类所有功能的新类,即它继承了父类的功能。

以Circle 和 Rectangle 类为例:

@ubterface Circle : NSObject
{
@private
ShapeColcor fillColor;
ShapeRect bounds;
}
- (void) setFillColor: (ShapeColor) fillColor;
- (void) setBounds: (ShapeRect) bounds;
- (void) draw;
@end // Circle


@interface Rectangle : NSObject
{
@private
ShapeColor fillColor;
ShapeRect bounds;
}
- (void) setFillColor: (ShapeColor) fillColor;
- (void) setBounds: (ShapeRect) bounds;
- (void) draw;
@end // Rectangle


这两个类接口除了名称,其他都是相同的。

再看两个类的实现:

@implementation Circle
- (void) setFillColor : (ShapeColor) c
{
fillColor = c;
} // setFillColor
- (void) setBound : (ShapeRect) b
{
bounds = b;
} // setBounds
@end // Circle


@implementation Rectangle
- (void) setFillColor : (ShapeColor) c
{
fillColor = c;
} // setFillColor
- (void) setBound : (ShapeRect) b
{
bounds = b;
} // setBounds
@end // Rectangle


这些方法具有完全一样的功能。不过
draw
方法的名称和参数虽然一样,但是实现却不同。

@implementation Circle
- (void)draw
{
NSLog (@"drawing a circle at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.width,
bounds.height,
colorName(fillColor);
);
} // draw
@end // Circle


@implementation rectangle
- (void)draw
{
NSLog (@"drawing rect at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.width,
bounds.height,
colorName(fillColor);
);
} // draw
@end // Rectangle


将所有重复的内容合并在一起,还能在需要的地方拥有自定义的方法,这就是 继承 的特性。

下面创建一个新类Shape ,用于保存共有的实例和声明方法。
Circle
类和
Rectangle
类将从
Shape
类继承而来。

@interface Shape : NSObject //冒号后面的标识符就是需要继承的类
{
ShapeColor fillColor;
ShapeRect bounds;
}
- (void) setFillColor: (ShapeColor) fillColor;
- (void) setBounds: (ShapeRect) bounds;
- (void) draw;
@end // Shape


@implementation Shape
- (void) setFillColor : (ShapeColor) c
{
fillColor = c;
} // setFillColor
- (void) setBound : (ShapeRect) b
{
bounds = b;
} // setBounds
// 定义一个空的draw方法,以便Shape的子类通过他来实现各自的方法。
- (void) draw
{
} // draw
@end // Shape


Circle 类的接口和实现

@interface Circle : Shape
@end // Circle


@implementation Circle
- (void)draw
{
NSLog (@"drawing a circle at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.width,
bounds.height,
colorName(fillColor);
);
} // draw
@end // Circle


Rectangle 类的接口和实现

@interface Rectangle : Shape
@end // Rectangle


@implementation Rectangle
- (void)draw
{
NSLog (@"drawing Rect at (%d %d %d %d) in %@",
bounds.x,
bounds.y,
bounds.width,
bounds.height,
colorName(fillColor);
);
} // draw
@end // Rectangle


代码精简了,功能相比之前没有任何变化。而且不需要更改
main()
函数中设置和使用对象的任何代码。

调用继承的方法

当代码发送消息时,Objective-C 的方法调度机制将在当前的类中搜索相应的方法,如果无法在接收消息的对象的类文件中找到相应的方法,它就会在该对象的超类中进行查找。


4000
于类似
[shape setFillColor : RedColor]
的代码,Objective -C 首先会寻找接收消息的对象,在这里就是Circle类的对象。该对象拥有一个指向Circle类的指针,Circle类也有一个指向其相应代码的指针。调用程序通过这些指针来查找正确的代码。如果Circle类中没有定义该方法,接下来它将在超类Shape中查找相应的方法。假如方法在Circle和Shape类中都没有找到,调用程序会继续在NSObjecr类中去寻找,因为它是继承链中的下一个超类。如果在最顶层的NSObject类中也没有找到该方法,则会出现一个运行时错误,同时出现一个编译时警告错误。

实例变量

创建新类时,对象首先从他的超类继承实例变量,然后根据自身情况添加新的实例变量。

比如一个新类
RoundedRectangle
,这个类的接口定义如下:

@interface RoundedRectangle : Shape
{
@private
int radius;
}
@end // RoundedRectangle


NSObject类声明一个名为isa的实例变量,该变量保存一个指向对象当前类的指针。接下来是由Shape类声明的两个实例变量
fillColor
bounds
。最后是由RoundedRectangle声明的实例变量
radius
。每个方法调用都获得一个名为self的隐藏参数。它是一个指向接收消息的对象的指针。这些方法通过self参数来寻找它们需要用到的实例变量。

方法重写

制作新类时,经常会添加自己的方法,或者替换某个超类定义的现有方法。Objective提供了super 关键字,让人既可以重写方法的实现,又能调用超类中的实现方式。

以Circle 类举例:

@implementaion Circle
- (void) setFillColor : (ShapeColor) c
{
if (c == RedColor) // 检查ShapeColor类的参数是不是红色
{
c = GreenColor; // 是,则改成绿色
}
[super setFillColor : c]; //请求超类响应消息
} // setFillColor
//Circle 类剩下的实现部分不变


当你向super发送消息时,实际上是在请求Objective-C向该类的超类发送消息。如果超类中没有地迎该消息,Objective-C继续在继承链的上一级中查找。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: