iOSInterviewQuestions
iOSInterviewQuestions copied to clipboard
21题“不推荐在 init 方法中使用点语法”
在提到“不推荐在 init 方法中使用点语法”之后,说了原因之后举了个例子:
在基类 Person 的默认初始化方法中,可能会将姓氏设为空字符串。此时若使用点语法( self.lastName )也即 setter 设置方法,那么调用将会是子类的设置方法
经过测试,运行代码[[Person alloc] init]
并不会调用子类的setter方法,而是会输出🔴类名与方法名:-[Person setLastName:](在第25行),描述:根本不会调用这个方法
,请查证。
那你在父类的init方法里面有木有调用点语法(self.lastName = xxx)额...
我也试过了. 和他是一样的结果. 在Person类init里调用setter, 应该不会到子类里找实现, 只会向上找吧? 你是不是说运行代码[[ChenPerson alloc] init], 在Person的init里的self.lastName = @"XXX";不会走Person中的setter, 而是调用子类ChenPerson中的setter? 这样的话就和这个例子上面的题目联系起来了...说明super最后调用的是self
这句话,出自《Effective Objective-C 2.0》的第7条“Access Instance Variables Primarily Directly When Accessing Them Internally”章节结尾处的第二条规律总结:
Within initializers and dealloc, always read and write data directly through instance variables.
在初始化方法和dealloc内部,总是直接读写实例变量。
原书引出这条规律,是因为章节前面内容说到:“写操作用setter,读操作用实例变量。但是有一个例外情况”,也就是说,写操作不用setter,而要用实例变量的情况。于是,才举了子类覆写父类setter方法的例子,来说明原因。
至于这个题目的解答中,出现的这句话:
这也就是为什么说“不推荐在 init 方法中使用点语法”,如果想访问实例变量 iVar 应该使用下划线( _iVar ),而非点语法( self.iVar )。
这跟[self class],[super class],没有直接因果关系。纯属神来一笔。这里的class,既不是属性,也不是实例变量,而是一个方法。
另外,原书的例子跟@ChenYilong的例子一样,但代码有一处问题。
- (void)setLastName:(NSString*)lastName {
if (![lastName isEqualToString:@"Smith"]) {
[NSException raise:NSInvalidArgumentException format:@"Last name must be Smith"]; } self.lastName = lastName;
}
setter里面,用到self.xxx,会导致死循环。
所以 在Person父类初始化时调用self.语法对name进行set时会调用子类的setter方法么
唐巧的《不要在init和dealloc函数中使用accessor》http://blog.devtang.com/2011/08/10/do-not-use-accessor-in-init-and-dealloc-method/