0x01 为什么要使用继承?
观察上一章用OOP思想写出来Circle和Rectangle的接口:
@interface Circle : NSObject
{
@private
ShapeColor 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
还有Circle和Rectangle的实现:
@implementation Circle
- (void)setFillColor:(ShapeColor)c
{
fillColor = c;
} // setFillColor
- (void)setBounds:(ShapeRect)b
{
bounds = b;
} // setBounds
// ...
@end // Circle
@implementation Rectangle
- (void) setFillColor: (ShapeColor) c
{
fillColor = c; } // setFillColor
- (void)setBounds:(ShapeRect)b
{
bounds = b;
} // setBounds
// ...
@end // Rectangle
程序中有大量结构相似的代码,其中的接口和实现都显得非常相似,甚至除了名称不同,其他都是相同的。
当编程过程中出现这样的重复内容,就意味着这是一个失败的架构。
维护两倍以上的代码,意味着修改代码时必须修改多处,这样做将提高出错几率。
继承将是一个重要的OOP特性,使得合并相似代码成为可能。
我们可以创建一个全新的Shape类,用于保存Circle类和Rectangle类共有的实例变量和声明方法,Circle类和Rectangle类各自特有的draw方法仍然自己保留。

0x02 继承的语法格式
@interface Circle: NSObject
1、冒号后面的标识符是需要继承的类。在Objective-C中可以选择不继承,但使用了Cocoa框架,就需要继承NSObject类,因为它提供了大量有用的特性;
2、Objective-C不同于C++,前者不支持多继承。
引入继承特性,Circle和Rectangle的接口精简如下:
@interface Circle : Shape
@end // Circle
@interface Rectangle : Shape
@end // 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)setBounds: (ShapeRect)b
{
bounds = b;
} // setBounds
- (void) draw
{
} // draw
@end // Shape
1、draw方法在此没有实现任何功能,因为它将在不同的类中有不同的实现。但我们仍然需要在此定义它,以便Shape的所有子类能够通过它来实现各自的方法;
2、在方法定义中不写任何内容或者返回一个虚值(dummy)都是可以通过编译的。
然后再写Circle类和Rectangle类的实现,他们将变得非常简单:
@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
从始至终,我们都不需要改变main( )函数中的代码,因为我们没有改变对象响应的办法,也没有改变它们的行为。