iOS精选面试题(基础篇)
面试题目都是网上收集,回答是自己尝试回答,网上的很多回答我觉得不一定对,会自己修改,有问题希望可以及时指出来
1.Object-c的类可以多重继承么?可以实现多个接口么?Category是什么?重写一个类的方式用继承好还是分类好?为什么?
1.OC没有多重集成
2.但可以遵循多个协议也就是protocol
3.Category是类别
4.重写一个类的方式,用继承好还是分类好?为什么?
这个问题中“重写”和“方式”这两个词就很奇怪,这个类如果是你自己写的,对不满意的地方直接修改就可以了,干嘛要继承和分类登场呢?即使这个类你没源码,但是你对这个类各种不满意,你要重写一个类代替,也跟继承和分类没直接关系啊。
我从两个方向去尝试猜测下这道面试题的意思,
猜测1:“方式”改为“”方法“,面试官是想问重写一个类的方法,用继承好还是分类好?这里网上的很多回答已经严重不对了,例如网上大多回答是这样的:
“ 一般情况用分类好,用Category去重写类的方法,仅对本Category有效,不会影响到其他类与原有类的关系”这个回答如果回答者的意思是说如果其他类没有引入这个分类,就不会调用到分类的实现,还会是这个类原有的实现,就打错特错了,实际上如果只要你分类覆盖了这个类的某个方法的实现,你在工程中即使不引入这个分类,也都会调用到分类的实现。
我们可以写代码试下:我们先新建一个工程,然后写一个Test的类,直接继承NSObject就好,然后我们定义了两个方法,一个方法让分类直接覆盖,一个分类间接覆盖真正的实现
- (NSString *)whoAmI;
//让分类直接覆盖- (void)indirectMethodTest;
//分类覆盖间接的方法
实现代码如下
- (NSString *)whoAmI {
return @"Test";
}- (void)indirectMethodTest {
[self iAmDirect];
//真正调用的是iAmDirect
}- (void)iAmDirect {
NSLog(@"iAmDirect Test");
}
然后我们让分类分别实现,“whoAmI”和“iAmDirect”
- (NSString *)whoAmI {
return @"Test+Change";
}- (void)iAmDirect {
NSLog(@"iAmDirect Test+Change");
}
我们在控制其中不引入类别只引入Test.h
文章图片
控制器viewDidLoad加入如下代码
Test *test = [Test new];
NSString *string = [test whoAmI];
NSLog(@"string = %@", string);
[test indirectMethodTest];
然后控制台打印下这两个方法的结果
【iOS精选面试题(基础篇)】
文章图片
可以发现即使你没引入类别,这个类的实现,也会被分类的方法替换掉,具体原因,可以看下分类的实现原理,我以后会详细说下,简单来说就是runtime把categoray实现的方法,放在了原来类方法的前面,这样必定每次都会先找到分类的方法。不过要记住分类只会覆盖这个类的原有实现,对子类是不会覆盖的,这个是msgsend的调用流程决定的。
所以针对猜测1,重写一个类的方法来说,我觉得用继承最好,除非你真的觉得这个原来的方法没救了,你要一劳永逸的替换原有类的实现,而且不想修改使用到这个方法的其他类的代码了,你也已经通知了你在的开发组同事了,你可以去这么做,不过这种方式实在不明智,连苹果都给了警告不要这么做
”Category is implementing a method which will also be implemented by its primary class“用继承的方式则要好的多:
1.你用子类重写这方法之后,你只需要在不满意的地方,用子类替换即可,不需要改的地方,还可以继续使用以前的类。
2.可以使用super调用这个类的原来的实现前后,子类做一些修改,因为子类的super指向的是这个类,而类别的super,指向的是还是这个类的父类,因为类别毕竟不是继承啊。
猜测2:重写改为扩展,面试官想问:扩展一个类的方式,用继承好还是分类好?为什么?
这个好回答很多,就是问继承和分类的区别,优劣势。
继承:
1.要重写原来类中的方法,但父类的这个方法也想继续使用。
2.增加成员变量,属性
类别:
1.系统特定类没法继承,重点说的就是类簇,比如NSString,NSArray,NSNumber等,这些返回的真实的类,都是一些私有隐藏的类,如果继承,将相当麻烦。相反使用类别去扩展一些功能,将方便很多。
2.用分类,将一些复杂的类,按功能将的方法拆分到单独的文件中,可以提高可维护性,iOS系统中的类就经常这么做。例如把NSObject延时执行的方法例如:
(void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay
等方法放到了runloop文件中,因为这些方法runloop相关的。
持续更新中。。。
推荐阅读
- PMSJ寻平面设计师之现代(Hyundai)
- 杜月笙的口才
- 2020-04-07vue中Axios的封装和API接口的管理
- iOS中的Block
- Linux下面如何查看tomcat已经使用多少线程
- 皮夹克
- 解读《摩根集团》(1)
- 绘本与写作
- 记录iOS生成分享图片的一些问题,根据UIView生成固定尺寸的分享图片
- 麦田社群