0%

子类同名父类私有属性和方法

对于私有属性和方法,子类和父类同名基本上没有什么影响.但是有几点需要注意一下:

如果是属性同名,子类和父类会拥有各自独立的实例变量。

如果是方法同名,按照消息发送的过程,执行的自然是子类中的方法。

举个栗子:

父类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@interface Animal : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;

- (void)hello;

@end

@interface Animal ()

@property (nonatomic, copy) NSString *hobbit;

@end

@implementation Animal

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age {
self = [super init];
if (self) {
_name = name;
_age = age;
}
return self;
}

- (void)hello {
NSLog(@"父类方法,%@ %ld %@", _name, (long)_age, self.hobbit);
}

- (void)run {
NSLog(@"父类方法run");
}

- (NSString *)hobbit {
if (_hobbit == nil) {
_hobbit = @"unknown";
}
return _hobbit;
}

@end

子类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@interface Person : Animal

@end

@interface Person ()

@property (nonatomic, copy) NSString *hobbit;

@end

@implementation Person

- (void)hello {
[super hello];

NSLog(@"子类方法,%@ %ld %@", self.name, (long)self.age, self.hobbit);

[self performSelector:@selector(run)];
}

@end

属性同名,拥有各自独立的实例变量:

方法同名:

下面代码会打印什么?

1
2
3
4
5
Person *p = [[Person alloc] initWithName:@"mattt" age:3];
[p hello];

Animal *ani = [[Animal alloc] initWithName:@"sun" age:3];
[ani hello];

打印:

1
2
3
4
2020-03-23 10:17:13.648428+0800 父子类属性同名[47652:6589153] 父类方法,mattt  3 (null)
2020-03-23 10:17:13.648780+0800 父子类属性同名[47652:6589153] 子类方法,mattt 3 (null)
2020-03-23 10:17:13.648815+0800 父子类属性同名[47652:6589153] 父类方法run
2020-03-23 10:17:13.648853+0800 父子类属性同名[47652:6589153] 父类方法,sun 3 unknown

可以看到父类的hobbit属性是实现了懒加载的,但子类执行到父类hello方法里的self.hobbit时并没有执行懒加载代码,打印依然为null。这是因为执行self.hobbit时,执行的是子类自己的getter/setter方法。

之所以写这个,是因为在重构的时候发现上面的懒加载代码怎么死活都不执行。

觉得文章有帮助可以打赏一下哦!