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

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

实例变量

创建新类时,对象首先从他的超类继承实例变量,然后根据自身情况添加新的实例变量。
比如一个新类RoundedRectangle,这个类的接口定义如下:

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

NSObject类声明一个名为isa的实例变量,该变量保存一个指向对象当前类的指针。接下来是由Shape类声明的两个实例变量fillColorbounds。最后是由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继续在继承链的上一级中查找。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值