07-继承使用过程中的注意点(含代码)

1、父类必须写在子类之前

 1 #import <Foundation/Foundation.h>
 2 @interface Student : Person
 3 @end
 4 
 5 @implementation Student
 6 @end
 7 
 8 @interface Person : NSObject
 9 @end
10 
11 @implementation Person
12 @end
13 
14 int main()
15 {
16     return 0;
17 }

由于编译器读取代码是从上到下逐行读取的,当读到第2行的时候,会找不到Person类,于是报错

正确写法如下:

 1 #import <Foundation/Foundation.h>
 2 @interface Person : NSObject
 3 @end
 4 
 5 @implementation Person
 6 @end
 7 
 8 @interface Student : Person
 9 @end
10 
11 @implementation Student
12 @end
13 
14 int main()
15 {
16     return 0;
17 }

2、子类可以拥有父类所有的成员变量和方法

  1>父类中已有的成员变量,子类中不能重复声明。即不允许子类和父类拥有相同名称的成员变量

下面的代码是错误的:

 1 #import <Foundation/Foundation.h>
 2 @interface Person : NSObject
 3 {
 4     int _age;
 5 }
 6 @end
 7 
 8 @implementation Person
 9 @end
10 
11 @interface Student : Person
12 {
13     int _age;//此处重复声明成员变量_age
14 }
15 @end
16 
17 @implementation Student
18 @end
19 
20 int main()
21 {
22     return 0;
23 }

报错:重复声明成员变量 _age

  2>父类中声明实现的方法,子类可以重复声明实现(如果要实现子类自己的功能,可以重写方法,本例重写了run方法)

下面的代码是正确的

 1 #import <Foundation/Foundation.h>
 2 @interface Person : NSObject
 3 {
 4     int _age;
 5 }
 6 - (void)run;
 7 @end
 8 
 9 @implementation Person
10 - (void)run
11 {
12     NSLog(@"Person---跑");
13 }
14 @end
15 
16 @interface Student : Person
17 
18 - (void)run;
19 @end
20 
21 @implementation Student
22 - (void)run
23 {
24     NSLog(@"Student---跑");
25 }
26 @end
27 
28 int main()
29 {
30     return 0;
31 }

  3>自己可以在不改变父类原有成员变量和方法的情况,拓充自己的成员变量和方法

代码如下:

 1 #import <Foundation/Foundation.h>
 2 @interface Person : NSObject
 3 {
 4     int _age;
 5 }
 6 - (void)run;
 7 @end
 8 
 9 @implementation Person
10 - (void)run
11 {
12     NSLog(@"Person---跑");
13 }
14 @end
15 
16 @interface Student : Person
17 {
18     int _weight;//子类拓充的成员变量,父类中没有
19 }
20 
21 - (void)run;
22 - (void)eat;//子类拓充的方法,父类中没有
23 @end
24 
25 @implementation Student
26 - (void)run
27 {
28     NSLog(@"Student---跑");
29 }
30 - (void)eat
31 {
32     NSLog(@"Student---吃");
33 }
34 @end
35 
36 int main()
37 {
38     return 0;
39 }

3、方法的访问

 1 #import <Foundation/Foundation.h>
 2 @interface Person : NSObject
 3 {
 4     int _age;
 5 }
 6 - (void)run;
 7 @end
 8 
 9 @implementation Person
10 - (void)run
11 {
12     NSLog(@"Person---跑");
13 }
14 @end
15 
16 @interface Student : Person
17 @end
18 
19 @implementation Student
20 @end
21 
22 int main()
23 {
24     Student *s = [Student new];
25     [s run];
26     return 0;
27 }

原理:每个对象中隐藏着一个isa指针,每个类中隐藏着一个superclass指针

(1)当对象s调用run方法,通过隐藏的isa指针优先去s对应的Student类中去寻找run方法;

(2)当在Student类中没有找找run方法时,就会通过superclass指针去父类Person中寻找run方法;

(3)在父类中招到了run方法,执行之;如果没找到,会一直往上找直到NSObject类。

当执行第25行代码的时候,对象s调用run方法,它会优先去当前对象所对应的类中去寻找run方法,发现子类中没有run方法,它就会去父类中找run方法

如果一直找不到就会报经典错误。

执行结果如下:

4、方法的重写

  子类重新实现父类中已经存在的某个方法,覆盖父类以前的做法

 1 #import <Foundation/Foundation.h>
 2 @interface Person : NSObject
 3 {
 4     int _age;
 5 }
 6 - (void)run;
 7 @end
 8 
 9 @implementation Person
10 - (void)run
11 {
12     NSLog(@"Person---跑");
13 }
14 @end
15 
16 @interface Student : Person
17 - (void)run;
18 @end
19 
20 @implementation Student
21 - (void)run//重写:子类重新实现父类中的某个方法,覆盖掉父类以前的做法
22 {
23     NSLog(@"Student---跑");
24 }
25 @end
26 
27 int main()
28 {
29     Student *s = [Student new];
30     [s run];
31     return 0;
32 }

总结:

(1)父类必须声在子类的前面

(2)不允许子类和父类拥有相同名称的成员变量

(3)允许子类对父类中的方法进行重复声明和实现

(4)找方法:当调用方法时,优先去当前类中去找,找不到了再去父类找

(5)方法重写:子类重新实现父类中已经存在的某个方法,覆盖父类以前的做法

人生之路,不忘初心,勿忘始终!
原文地址:https://www.cnblogs.com/xdl745464047/p/3999625.html