Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the advantages and disadvantages of using Protocol vs Inheritance? [closed]

In objective-c?

I had a class made and then I decided that I want another class that's like the first class. Should I use protocol and ensure that both classes support that protocol or should I create a parent class and decide that the 2 classes inherit from that one class?

Note:

The classes are: Business, Catalog, AddressAnnotation (currently works only on business only) and AddressAnnotationView (currently works only on business only). I want the same thing to work on Catalog. There is also BGGoogleMapCacheForAllAnnotations that manage when the annotations are clumped together (which now should be able to handle both AddressAnnotation for Catalog and Business. Also there is BGGoogleMap View Controller that I want to turn into a parent class.

like image 799
user4951 Avatar asked Feb 14 '13 03:02

user4951


2 Answers

If you use a protocol, then you have to define methods shared by both class types twice. Protocols are generally reserved for specific patterns, such as the delegation pattern, to add security and make it harder for you to make a mistake, or when several classes already embedded in a class hierarchy need to share common methods and have this sharing be documented in some way. If one class can be represented as a more specialized version of another, you should inherit.

For instance, let's say you you have a Vehicle class in your game that knows how to do all sorts of stuff, such as move around. If you wanted to make a Car class, you'd probably subclass the Vehicle class so that you could inherit all of its method implementations; either to utilize them wholesale or implement your own version of the methods, probably performing some task specific to the subclass before calling the superclass's implementation as well. Subclassing is for when you want to inherit the traits and behaviors of your superclass while modifying it in some way. This is especially true when additional data must be added to the class, such as instance variables, because you can't do that with categories (although you can with a Class Extension, often seen as a sort of private interface). Generally, subclasses have more specialized purposes than their superclasses as a result.

Protocols are just that, protocols. They're there to prevent you from screwing up or forgetting something, and ensure that every object does what it's supposed to, triggering compiler warnings when classes aren't behaving like they are supposed to. This is important for patterns such as delegation, since it's the only way to ensure that the delegate implements the methods you need beyond breaking encapsulation and knowing what type of object your delegate is. For instance, look at the the code below, from one of my projects.

//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

Many classes utilize my SGSprite class for rendering textured 2D quads. Sometimes, they need to know when a sprite reaches a certain frame of animation, so SGSprite instances need to call a method on their delegates to let them know when certain frames are reached. The only way to ensure that delegates to instances of this class implement this method, and, indeed, warn me if someone tries to assign an object that doesn't as a delegate, is through the use of a protocol. You'll notice that if I simply make the delegate a plain id I'll get a warning whenever I call this method on my delegate, since its implementation cannot be found, while if I import the delegate's header/statically type the delegate, the class is no longer well encapsulated.

You don't technically need protocols in most cases; you could define all of the methods without a protocol in all of the classes that would ordinarily adhere to said protocol, and everything would work fine. However, these common methods are no longer documented. Thus, beyond the security of knowing certain classes or anonymous objects implement methods you need them to implement, you can also quickly tell what does what and how. Protocols are for when you need to ensure that a class, or instance of a class, implements some method, especially when an object's type shouldn't be known to keep a class encapsulated.

like image 193
Metabble Avatar answered Jan 03 '23 10:01

Metabble


There are a lot of factors that could influence that decision. For one, when you say that the other class is "like the first class", what does that mean? Does it mean that they'll do 90% of the same things in exactly the same way? Does it mean that they'll do a lot of the same kinds of things, but each in a slightly different way?

If many of the existing methods in the first class will work as-is or with little modification in the second class, subclassing lets you get all of those methods "for free" so you can just focus on the differences. If you would need to rewrite most of the code, however, and just want to define the two classes as performing similar actions then a protocol might make more sense.

I've personally used subclassing exclusively, primarily because I haven't run into a situation where a protocol made sense to me in my code - of course, after a while it's more out of habit than conscious decision. When I began converting my app to using Core Data, subclassing fit in very nicely because Core Data offers the ability to create subentities with inherited attributes and relationships. That made it easier to grasp conceptually.

If you think about your current code, you're already subclassing (NSObject, view controllers, etc.) and possibly using protocols (NSCoding, view delegates, etc.). Think about how you use those existing classes and protocols and how those use cases would apply to your own classes.

like image 22
David Ravetti Avatar answered Jan 03 '23 11:01

David Ravetti