看官们,我们在上一章回中通过具体的代码演示了如何使用继承,带着上一章回末尾的问题,本章回中将介绍方法的重写。
方法的重写通常发生在类继承的过程中,具体表现为子类中定义的方法和父类中某个方法相同,或者说子类和父类中拥有相同名字的方法。接下来我们通过具体的代码说明。
#import<Foundation/Foundation.h>
//定义父类Phone,类中包含两个属性和一个方法
@interface Phone : NSObject
@property char * name;
@property int size;
-(void) makeCall;
@end
//实现父类Phone。主要是实现了init和makeCall方法
@implementation Phone
@synthesize name;
@synthesize size;
-(instancetype) init {
self = [super init];
if(self) {
name = "this is phone";
size = 0;
}
return self;
}
-(void) makeCall {
NSLog(@"Phone makeCall");
}
@end
@interface AndroidPhone : Phone
-(void) os;
@end
@implementation AndroidPhone
-(instancetype) init {
self = [super init];
if(self) {
[super setName:"this is AndroidPhone"];
[super setSize:7];
}
return self;
}
-(void) os {
NSLog(@"this is AndroidPhone");
}
@end
//定义子类IPhone,继承自父类:Phone。子类定义了appleID属性和os方法
@interface IPhone : Phone
@property char* appleID;
-(void) os;
@end
@implementation IPhone
@synthesize appleID;
-(instancetype) init {
self = [super init];
if(self) {
appleID = "001";
//不能直接使用父类的的成员,因为其此成员拥有私有权限。需要通过设置方法来修改父类成员的值
// name = "this is IPhone";
// size = 6;
[super setName: "this is IPhone"];
[super setSize:6];
}
return self;
}
-(void) os {
NSLog(@"this is IOS");
}
-(void) makeCall {
NSLog(@"IPhone makeCall");
}
@end
int main() {
NSLog(@"this is main application");
Phone *phone = [[Phone alloc] init];
IPhone *iPhone = [[IPhone alloc] init];
AndroidPhone *aPhone = [[AndroidPhone alloc] init];
[phone makeCall];
NSLog(@"Name: %s, size: %d",phone.name,phone.size);
[iPhone os];
[iPhone makeCall];
NSLog(@"Name: %s, size: %d,appleID: %s",iPhone.name,iPhone.size,iPhone.appleID);
[aPhone os];
[aPhone makeCall];
NSLog(@"Name: %s, size: %d",aPhone.name,aPhone.size);
}
上面的代码中,我们定义了父类Phone和子类AndroidPhone。这部分代码我们在上一章回中介绍过,因此这里不再做详细介绍。
我们重写看一下新定义的子类IPhone,它继承了自父类Phone,拥有父类的属性和方法,在此基础上它定义了自己的属性和方法.不过makeCall方法和父类重名了,这时便发生了重写,我们通过子类对象调用makeCall方法时调用的是子类的makeCall方法而不是父类的makeCall方法,因为子类的makeCall方法覆盖了父类的makeCall方法。
我们可以做个对比,AndroidPhone也是继承自父类Phone,但是它没有重写父类的makeCall方法,因此它的对象调用makeCall方法时调用的是父类的方法。
刚才所说的对比,我们在main函数中进行了验证,下面是程序运行的结果,大家可以自己动手去验证。
另外,代码中的两个子类都定义了相同的os方法,但是此方法没有发生重写,因为父类没有相同的os方法。希望大家不要一看到相同的方法就认为是重写方法,要注意区分。
$ clang -framework Foundation oop.m -o ex.out //把上面的代码保存为oop.m然后编译该程序
$ ./ex.out //运行编译后的程序
ex.out[2023:144432] this is main application
ex.out[2023:144432] Phone makeCall //父类Phone的方法和属性
ex.out[2023:144432] Name: this is phone, size: 0
ex.out[2023:144432] this is IOS //子类IPhone调用自己的os方法,该方法没有发生重写
ex.out[2023:144432] IPhone makeCall //子类IPhone重写了父类的makeCall方法,调用得是自己的方法
ex.out[2023:144432] Name: this is IPhone, size: 6,appleID: 001
ex.out[2023:144432] this is AndroidPhone //子类AndroidPhone调用自己的os方法,该方法没有发生重写
ex.out[2023:144432] Phone makeCall //子类AndroidPhone没有重写父类的makeCall方法,调用的是父类的方法
ex.out[2023:144432] Name: this is AndroidPhone, size: 7
最后我们对本章回的内容做一个总结:
- 1.重写发生在类的继承体系中,表现为父类和子类拥有相同的方法;
- 2.发生重写方法后调用的是子类的方法,父类的方法被覆盖了;
- 3.不同子类拥有相同的方法不能称作是重写方法;
看官们,欲知后事如何且听下回分解!