使用Protocol vs Inheritance有什么优缺点?

时间:2013-02-14 03:11:07

标签: objective-c inheritance

在objective-c?

我上了一堂课,然后我决定要另一堂课,就像第一堂课一样。我应该使用协议并确保两个类都支持该协议,还是应该创建一个父类并确定这两个类是否从该类继承?

注意:

这些类是:Business,Catalog,AddressAnnotation(目前仅适用于业务)和AddressAnnotationView(目前仅适用于业务)。我想在Catalog上使用相同的东西。还有BGGoogleMapCacheForAllAnnotations可以管理注释何时聚集在一起(现在应该能够同时处理Catalog和Business的AddressAnnotation。还有BGGoogleMap View Controller我想转变为父类。

2 个答案:

答案 0 :(得分:7)

如果使用协议,则必须定义两种类类型共享的方法两次。协议通常保留用于特定模式,例如委托模式,以增加安全性并使您更难以犯错,或者已经嵌入在类层次结构中的几个类需要共享公共方法并将此共享记录在某种方式。如果一个类可以表示为另一个类的更专业版,则应该继承。

例如,假设您在游戏中有一个Vehicle类,它知道如何做各种各样的事情,比如四处走动。如果你想创建一个Car类,你可能会继承Vehicle类,这样你就可以继承它的所有方法实现;要么批量使用它们,要么实现自己的方法版本,可能在调用超类的实现之前执行特定于子类的任务。 子类化是指您希望在以某种方式修改它的同时继承超类的特征和行为。当必须将其他数据添加到类(例如实例变量)时尤其如此,因为您不能用类别做到这一点(尽管你可以使用Class Extension,通常被视为一种私有接口)。通常,子类比其超类具有更专业的目的。

协议只是协议。他们在那里是为了防止你搞砸或遗忘某些东西,并确保每个对象都能达到预期的效果,当类不符合预期时,会触发编译器警告。这对于委托等模式很重要,因为它是确保委托实现除了打破封装和知道委托的对象类型之外所需的方法的唯一方法。例如,从我的一个项目中查看下面的代码。

//SGSprite.h
@protocol SGSpriteDelegate
    - (BOOL) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
@end

@interface SGSprite : NSObject
@property (nonatomic, assign) id<SGSpriteDelegate> delegate;
@end

//SGViewController.h
@interface SGViewController : UIViewController <SGSpriteDelegate>
    //...dreadfully boring stuff
@end

许多类使用我的SGSprite类来渲染纹理2D四边形。有时,他们需要知道sprite何时到达某个动画帧,因此SGSprite个实例需要在其委托上调用一个方法,让他们知道何时到达某些帧。确保此类实例的委托实现此方法的唯一方法,并且实际上,如果有人尝试分配不作为委托的对象,则警告我是通过使用协议。您会注意到,如果我只是让委托变为普通id我会在我的委托上调用此方法时收到警告,因为无法找到它的实现,而如果我导入委托的标头/静态类型代表,该类不再被很好地封装。

在大多数情况下,您在技术上不需要协议;您可以在通常遵守所述协议的所有类中定义所有没有协议的方法,并且一切都可以正常工作。但是,不再记录这些常用方法。因此,除了知道某些类或匿名对象实现您需要它们实现的方法的安全性之外,您还可以快速了解什么是什么以及如何实现。 协议适用于需要确保类或类实例实现某种方法的情况,尤其是当不知道对象的类型以保持封装类时。

答案 1 :(得分:3)

有很多因素可能会影响这一决定。首先,当你说另一个班级“像头等舱”时,这是什么意思?这是否意味着他们会以完全相同的方式完成90%的相同事情?这是否意味着他们会做很多相同类型的事情,但每个事情都会略有不同?

如果第一个类中的许多现有方法将按原样工作或在第二个类中稍作修改,则子类化允许您“免费”获取所有这些方法,因此您可以只关注差异。但是,如果您需要重写大部分代码,并且只想将两个类定义为执行类似的操作,那么协议可能更有意义。

我个人专门使用子类化,主要是因为我没有遇到协议在我的代码中对我有意义的情况 - 当然,在一段时间之后,它更多地出于习惯而不是有意识的决定。当我开始将我的应用程序转换为使用Core Data时,子类化非常合适,因为Core Data提供了使用继承属性和关系创建子实体的能力。这使得从概念上更容易掌握。

如果你考虑当前的代码,你已经在子类化(NSObject,视图控制器等),并且可能使用协议(NSCoding,查看委托等)。考虑一下如何使用现有的类和协议,以及这些用例如何应用于您自己的类。