Pranshu
Pranshu

Reputation: 450

Subclass or Protocol, How to?

I'm developing an iOS application where I have a screen which displays some filters for a related search. Now I've made all of these filters as custom UIViews because they all have fairly different UI and they have to be reused on different screens. Inspite of their differences they all present a common interface to the View Controller managing them, so the view controller isn't concerned with what and how a filterView does something. It's only concerned with passing some data to them and retrieving their state through a property common to all of them. They all have their different classes which are subclasses of FilterView a subclass of UIView. This FilterView class presents an interface which all of these subclasses adopt.

This methodology works fine, but the problem is that all of the methods and properties a filterView should present are declared in the base class FilterView and if some particular filter doesn't implement a behavior it defaults to the behavior provided by its superclass FilterView. I don't want this. I want that every FilterView subclass should be required to provide an implementation on the FilterView API or otherwise provide their own defaults not the defaults of a superclass.

If I use a protocol to implement this behavior I loose the ability for all these classes to compulsorily be UIViews which is also a requirement.

Can you suggest what design pattern should I use to better manage all the different FilterView subclasses.

Upvotes: 0

Views: 415

Answers (3)

Pranshu
Pranshu

Reputation: 450

This can be expressed clearly now in swift 4 by defining the common interface in a protocol named Filter and then defining FilterView as:

typealias FilterView = UIView & Filter

Upvotes: 0

Sandeep Ahuja
Sandeep Ahuja

Reputation: 931

Define a protocol with non-optional methods -- "By default, all methods declared in a protocol are required methods. This means that any class that conforms to the protocol must implement those methods." Define a class that declares it implements the protocol. Now when a subclass of your parent class is written, the compiler will flag it as an error if the mandatory method(s) aren't implemented

and in super class you can write

//In super class
- (id)someMethod:(aObject*)param
{
     [self doesNotRecognizeSelector:_cmd];
     return nil;
}

Your app will crash if subclass will not implement this method and you don't need to call

[super someMethod: param];

Upvotes: 0

Losiowaty
Losiowaty

Reputation: 8006

Well, if you think that all your filter objects need to provide a UIView rather then explicitly being one, you can add this requirement to protocol. For example :

@protocol FilterObject 

- (UIView *)viewForFilter;

@end

// Swift
protocol FilterObject {
    func viewForFilter() -> UIView
}

And then in classes which actually are UIViews just implement it like this :

- (UIView *)viewForFilter {
    return self;
}

// Swift
func viewForFilter() -> UIView {
    return self
}

For completeness sake, you can also kind of "force" the requirement to implement methods in subclassess by throwing an exception when their base implementation is called :

- (void) methodWithoutBaseImplementation {
    // this goes in the base class
    [NSException raise:NSInternalInconsistencyException format:@"This method needs to be implemented by subclasses! - %@", NSStringFromSelector(_cmd)];
}

// Swift
func methodWithoutBaseImplementation() {
    NSException.raise(NSInternalInconsistencyException, format:"This method needs to be implemented by subclasses! - \(__FUNCTION__)")
}

This pattern to make Objective-C/Swift classess "abstract" can be foound in some of external libraries. Note that this is harder to achieve in Swift, as there is no dynamic dispatch in it - this means that if you cast your subclass to base class and call a method, the base implementation will be called. I'd advise against it though, as the protocol approach is safer, because it doesn't create a path where you crash your app. I've added this example just to illustrate the possibility and for completeness.

Upvotes: 2

Related Questions