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
iOS精选面试题(基础篇)
文章图片

控制器viewDidLoad加入如下代码
Test *test = [Test new]; NSString *string = [test whoAmI]; NSLog(@"string = %@", string); [test indirectMethodTest];

然后控制台打印下这两个方法的结果
【iOS精选面试题(基础篇)】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相关的。
持续更新中。。。

    推荐阅读