I have a base class which adds some functionality to a number of derived classes in my app.
One of these features is only used by some subclasses.
Currently I'm using a method which returns a BOOL which defaults to NO to "short-circuit" this feature. Subclasses which want the feature must override this method and return YES.
This feature is only useful if you've also overridden at least one of two other methods.
I'd prefer to use class_copyMethodList to determine if the subclass implemented either of these two methods (instead of using the method which returns a BOOL).
What barriers/roadblocks/cons to this approach should I be aware of? Is there a standard implementation of this idiom which I can use?
If I may suggest an alternative approach, have you considered using -instanceMethodForSelector on the relevant subclass instance and comparing to the result on the base class?
That method returns an IMP, which is a C function pointer to the implementation for the given selector. So if the subclass has a different implementation from the base class, it'll return a different IMP.
EDIT: as discussed in the comments below, a further alternative is to declare a formal protocol that the sub classes may implement, and to use NSObject's -conformsToProtocol: to determine whether the protocol is implemented. Since conformsToProtocol returns whether the class has declared support for the protocol (in its #interface via the angle brackets syntax), that's a lot like adding a custom BOOL method that defaults to returning NO but without the syntactic and semantic overhead of adopting your own ad hoc solution.
I have a base class which adds some functionality to a number of derived classes in my app.
This sentence should cause you to rethink your design. A base class should never do anything to derived classes. It should be ignorant of its subclasses. (Class Clusters notwithstanding. That's a separate design approach and require the superclass to be aware in the construction, making it the Factory pattern, which is fine.)
One of these features is only used by some subclasses.
This is a strong indication of a "Square/Rectangle" mistake. In OOP (forget ObjC, this is just CS theory), a square is not a rectangle. You need to ensure that your types conform to Liskov's Substitution Principle. Again, this has nothing to do with any particular language; it's true of all OOP design. It may seem very "theoretical" but it will seriously screw up your implementation if you fail LSP, and you will chase subtle bugs for much longer than you like.
The pattern you probably want here is Decorator rather than subclassing. If you have some special functionality that exists on some classes, you want to encapsulate that functionality into a separate object and attach it to subclasses where it makes sense. Another possible pattern is Strategy (which is generally implemented as a "delegate" in ObjC, which is another way of thinking about Decorator). The point is that you don't want logic in the superclass that is only applicable to some subclasses. You want to put that logic into something that only exists in the appropriate subclasses.
If all of those things fail you, then I strongly recommend a simple (BOOL) function over anything that introspects the method implementations. That way is fragile because it relies on ever-deeper implementation details. respondsToSelector: is definitely better than testing instanceMethodForSelector:.
Related
This is a pretty general question, but I was wondering today about delegates. At this point I don't really have a specific time I do use them or don't use them - aside from obvious cases, like passing selections from a picker or tableview stuff. For example, if there's a situation where I can pass a reference to an object around and use that to call methods, is there a reason to implement a delegate? In summary, what is the delegate pattern intended for use in and when is it better to NOT use it?
Thanks for the quick and comprehensive answers! They were all extremely helpful.
The advantage of the delegate pattern is loose coupling between the delegating object and its delegate. Loose coupling improves a class's reusability in other contexts.
The delegating object doesn't have to know anything about the object it communicates with (aside from the requirement that it implement the delegate protocol) – especially not its class or what methods it has. If you later want to reuse your component in a different context or have it communicate with another object of a different class, all this object has to do is implement the delegate protocol. The delegating object does not have to be changed at all.
There is also a downside to this, of course, and that is that a bit more code is required and the code you write is not as explicit and therefore may be a bit harder to understand. Whether this (generally small) tradeoff is worth it depends on your use case. If the two objects are tightly coupled anyway and the probability of reuse in the future is low, using the delegate pattern might be overkill.
See this discussion
A delegate allows one object to send messages to another object when an event happens.
Pros
Very strict syntax. All events to be heard are clearly defined in
the delegate protocol.
Compile time Warnings / Errors if a method is not implemented as it should be by a delegate.
Protocol defined within the scope of the controller only.
Very traceable, and easy to identify flow of control within an application.
Ability to have multiple protocols defined one controller, each with different delegates.
No third party object required to maintain / monitor the communication process.
Ability to receive a returned value from a called protocol method. This means that a delegate can help provide information back
to a controller.
Cons
Many lines of code required to define: 1. the protocol definition, 2. the delegate property in the controller, and 3. the implementation of the delegate method definitions within the delegate itself.
Need to be careful to correctly set delegates to nil on object deallocation, failure to do so can cause memory crashes by calling methods on deallocated objects.
Although possible, it can be difficult and the pattern does not really lend itself to have multiple delegates of the same protocol in a controller (telling multiple objects about the same event)
The "use case" for delegation is pretty much the same as for inheritance, namely extending a class behavior in a polymorphic way.
This is how the wikipedia defines delegation:
In software engineering, the delegation pattern is a design pattern in object-oriented programming where an object, instead of performing one of its stated tasks, delegates that task to an associated helper object. There is an Inversion of Responsibility in which a helper object, known as a delegate, is given the responsibility to execute a task for the delegator. The delegation pattern is one of the fundamental abstraction patterns that underlie other software patterns such as composition (also referred to as aggregation), mixins and aspects.
There are, obviously, many differences between delegation and inheritance, but the biggest one is, IMO, that inheritance is a fixed (aka, compile-time) relationship between two classes, while delegation can be defined at run-time (in languages that support this). On the other hand, inheritance offers better support for polymorphism.
Delegation is a huge topic (as inheritance is), and you can read a lot about it. In the end, deciding whether using delegation or inheritance comes down to deciding whether you want an "is-a" or and "has-a" relationship, so it is not so easy to list guidelines for choosing that.
For me, basically, the decision to create a delegate comes from the observation that:
my code presents a set of homogeneous behaviors (homogeneous here means that can be recognized as having a common "nature");
those behaviors might be be "customized" for particular cases (like in, replaced by alternative behaviors).
This is my personal view and a description of the way I get to identify "delegation" patterns. It has probably much to do with the fact that my programming discipline is strongly informed by the principle of refactoring.
Really, IMO, delegation is a way to define "customization" points for your class. As an example, if you have some kind of abstract workflow, where at each step you take some action depending on certain condition; and furthermore those concrete actions could be replaced by other of another kind, then I see there the chance of reuse through delegation.
Hope this helps.
I've been told recently a good practice in object oriented programming that you should always allow inheritance from your classes. I really don't think so, but I have no solid arguments on my mind.
Real-world examples of blocked inheritance:
No C++ STL class (specialized class template) allows inheritance (having non-virtual destructors).
Java has its final class modifier that applies to many standard components, like java.lang.String.
Possible reasons I think are:
Security, since subclass might have access to sensitive internals. (I don't think so -- they won't access private members.)
Performance, since a subclass could mess up our efficient implementations by overriding some of the member functions. (Children won't override non-virtual functions.)
To enforce composition over inheritance. (I fully agree. We shouldn't favor inheritance when it's not needed.)
So my question is: In what circumstances should I intentionally block inheritance?
In fact, the practice that I try to follow, and that Josh Bloch recommends, in his Effective Java book, is exactly the inverse rule of the one you've been told: Unless you have thought about inheritance, designed your class to be inherited, and documented how your class must be inherited, you should always disable inheritance.
I would recommend reading this chapter of Effective Java (you won't regret buying it), and showing it to the person who told you about this rule.
The most obvious reason to disallow inheritance is immutability. An immutable object is simple to use (only one state), can be cached, shared between many objects, and is inherently thread-safe. If the class is inheritable, anyone can extend the class and make it mutable by adding mutable attributes.
Well for starters, only disallow inheritance if you are positive that you don't want others to be extending your class. Preventing inheritance for trivial reasons (such as performance) is usually not recommended, as code reuse often outweighs the small performance gains you can achieve by marking your class final.
That being said, here are several examples when you might want to explicitly prevent inheritance:
You are writing a commercial, closed-source class, and you don't want people to be able to change the functionality down the line. This is a good reason to prevent class inheritance, as you don't want to have to give support for it later on if people have overridden your methods and/or extended your classes, and are complaining that they are getting unexpected results.
You are designing an immutable class. By marking the class final, you are preventing subclasses from compromising the immutable behavior of your class. For example, if you were allowed to subclass String, others could make their own implementations that allows Strings to be modified. Now no code that takes a type String can be certain that the object is immutable.
You want to force composition over inheritance. This is desirable when you want to avoid tight coupling between classes (i.e. you don't want groups of classes that are highly dependent on one another).
You want to encourage inlining by the compiler. Marking classes and methods as final may result in small performance gains, as it will ensure that Java doesn't have to look up the right class method to invoke for an object at runtime. Non-final methods are marked as virtual so that they can be properly extended if needed, final methods can be directly linked or compiled inline in the class. Note that the performance gain you can achieve by doing this is often insignificant (especially if your class' methods are large).
Just my 0.02 on this...
Allowing inheritance on a class allows people to deal with unforeseen issues. (ex. the monkeypatching that often occurs in RoR. It can be ugly but it's reality vs. pedantry). Having said that, I'm not a big fan of gratuitous inheritance. The relationship between base and subclasses can be brittle. Deep inheritance hierarchies are hard to grok.
One case I can think of disallowing inheritance is enforcing immutability. This is important for things like the Java String class.
I'm trying to understand whether the answer to the following question is the same in all major OOP languages; and if not, then how do those languages differ.
Suppose I have class A that defines methods act and jump; method act calls method jump. A's subclass B overrides method jump (i.e., the appropriate syntax is used to ensure that whenever jump is called, the implementation in class B is used).
I have object b of class B. I want it to behave exactly as if it was of class A. In other words, I want the jump to be performed using the implementation in A. What are my options in different languages?
For example, can I achieve this with some form of downcasting? Or perhaps by creating a proxy object that knows which methods to call?
I would want to avoid creating a brand new object of class A and carefully setting up the sharing of internal state between a and b because that's obviously not future-proof, and complicated. I would also want to avoid copying the state of b into a brand new object of class A because there might be a lot of data to copy.
UPDATE
I asked this question specifically about Python, but it seems this is impossible to achieve in Python and technically it can be done... kinda..
It appears that apart from technical feasibility, there's a strong argument against doing this from a design perspective. I'm asking about that in a separate question.
The comments reiterated: Prefer composition over inheritance.
Inheritance works well when your subclasses have well defined behavioural differences from their superclass, but you'll frequently hit a point where that model gets awkward or stops making sense. At that point, you need to reconsider your design.
Composition is usually the better solution. Delegating your object's varying behaviour to a different object (or objects) may reduce or eliminate your need for subclassing.
In your case, the behavioural differences between class A and class B could be encapsulated in the Strategy pattern. You could then change the behaviour of class A (and class B, if still required) at the instance level, simply by assigning a new strategy.
The Strategy pattern may require more code in the short run, but it's clean and maintainable. Method swizzling, monkey patching, and all those cool things that allow us to poke around in our specific language implementation are fun, but the potential for unexpected side effects is high and the code tends to be difficult to maintain.
What you are asking is completely unrelated/unsupported by OOP programming.
If you subclass an object A with class B and override its methods, when a concrete instance of B is created then all the overriden/new implementation of the base methods are associated with it (either we talk about Java or C++ with virtual tables etc).
You have instantiated object B.
Why would you expect that you could/would/should be able to call the method of the superclass if you have overriden that method?
You could call it explicitely of course e.g. by calling super inside the method, but you can not do it automatically, and casting will not help you do that either.
I can't imagine why you would want to do that.
If you need to use class A then use class A.
If you need to override its functionality then use its subclass B.
Most programming languages go to some trouble to support dynamic dispatch of virtual functions (the case of calling the overridden method jump in a subclass instead of the parent class's implementation) -- to the degree that working around it or avoiding it is difficult. In general, specialization/polymorphism is a desirable feature -- arguably a goal of OOP in the first place.
Take a look at the Wikipedia article on Virtual Functions, which gives a useful overview of the support for virtual functions in many programming languages. It will give you a place to start when considering a specific language, as well as the trade-offs to weigh when looking at a language where the programmer can control how dispatch behaves (see the section on C++, for example).
So loosely, the answer to your question is, "No, the behavior is not the same in all programming languages." Furthermore, there is no language independent solution. C++ may be your best bet if you need the behavior.
You can actually do this with Python (sort of), with some awful hacks. It requires that you implement something like the wrappers we were discussing in your first Python-specific question, but as a subclass of B. You then need to implement write-proxying as well (the wrapper object shouldn't contain any of the state normally associated with the class hierarchy, it should redirect all attribute access to the underlying instance of B.
But rather than redirecting method lookup to A and then calling the method with the wrapped instance, you'd call the method passing the wrapper object as self. This is legal because the wrapper class is a subclass of B, so the wrapper instance is an instance of the classes whose methods you're calling.
This would be very strange code, requiring you to dynamically generate classes using both IS-A and HAS-A relationships at the same time. It would probably also end up fairly fragile and have bizarre results in a lot of corner cases (you generally can't write 100% perfect wrapper classes in Python exactly because this sort of strange thing is possible).
I'm completely leaving aside weather this is a good idea or not.
I don't know if it is so complex like I say :P
This is the case use: I have a project with a lot of targets, and all use the same common code, but I create children class to use specific things. This is the spirit of object-oriented.
I have this hierarchy in program
NSObject -> ClassA_level_1 -> ClassA_level_2
NSObject -> ClassB_level_1 -> ClassB_level_2
ClassB_level_1 have a variable ClassA_level_1 *classA so call function in level1 is no problem. The problem is that ClassB_level_1 have to call things in ClassA_level_2 (NOT level 1) in some delegates function.
If in level_2 i can call super to get things in level_1, how can I do the opposite way? There are some tricky?
When you encounter this problem, you are most likely violating Liskov's Substitution Principle. In OOP, a square is not a rectangle.
If you are not violating LSP, then ClassB_level_1 should still not be calling anything in ClassA_level_2. ClassB_level_2 should be where that special logic is implemented, and it should therefore know the class of its delegate, and be able to assert that the class is correct and then cast to it. That said, if you find yourself here, it's often because of a more basic architectural problem.
First, reconsider your problem in terms of protocols rather than classes. What functionality do you really need from this other object? Check it with a protocol and respondsToSelector: rather than by asserting some class.
Could ClassB be a factory for ClassA so that it always creates the correct helper object? Perhaps you should reconsider this as a Class Cluster. When you find yourself creating complicated parallel hierarchies, often it's time to pull out Design Patterns and rethink your architecture. In particular, Decorator is often useful for problems that would otherwise lead to large parallel trees.
But if your design is correct, you just need to use respondsToSelector: to make sure your delegate responds to the method you want before calling it.
I'm trying to solve a design issue using inheritance based polymorphism and dynamic binding. I have an abstract superclass and two subclasses. The superclass contains common behaviour. SubClassA and SubClassB define some different methods:
SubClassA defines a method performTransform(), but SubClassB does not.
So the following example
1 var v:SuperClass;
2 var b:SubClassB = new SubClassB();
3 v = b;
4 v.performTransform();
would cause a compile error on line 4 as performTransform() is not defined in the superclass. We can get it to compile by casting...
(v as SubClassA).performTransform();
however, this will cause a runtime exception to be thrown as v is actually an instance of SubClassB, which also does not define performTransform()
So we can get around that by testing the type of an object before casting it:
if( typeof v == SubClassA)
{
(cast v to SubClassA).performTransform();
}
That will ensure that we only call performTransform() on v's that are instances of SubClassA. That's a pretty inelegant solution to my eyes, but at least its safe. I have used interface based polymorphism (interface meaning
a type that can't
be instantiated and defines the API of classes that implement it) in the past, but that also feels clunky. For the above case, if SubClassA and SubClassB implemented ISuperClass
that defined performTransform, then they would both have to implement performTransform(). If SubClassB had no real need for a performTransform() you would have to implement an empty function.
There must be a design pattern out there that addresses the issue.
My immediate comment is that your object modelling is wrong. Why treat SubClassA as a SuperClass (is-a relationship), when I would suggest that it's not.
You could implement a dummy performTransform() that does absolutely nothing in its base instance, and is overridden in SubClassA. But I'm still concerned that on one hand you're treating all these objects (SubClassA, SubClassB) as the same thing, and then wanting to treat them differently depending on their real implementation, rather than the interface they present.
Assuming you are using a strongly-typed language, which your question seems to indicate...
There is no design pattern to work around this, because this is the intended behavior.
In your definition, performTransform belongs only to SubClassA. Thus, to be able to invoke performTransform on an object, the object must be of type SubClassA (or a subtype of SubClassA.
Invoking performTransform on a SuperClass does not make sense because not every instance of SuperClass defines this method.
Downcasting from a SuperClass to a SubClassA should certainly throw an error if the instance is not a SubClassA - this should be obvious.
So, you must either change your definitions such that performTransform belongs to SuperClass (in which case, as you said, every instance of type SuperClass would need to have some implementation for the method, even an empty one) or you must make sure that you are only invoking methods on types that define them.
I'm not so sure it requires a pattern to solve but instead just a small redesign. If it makes sense for anything to call performTransform is should be in the superclass as a virtual method and overridden in the subclasses.
So the superclass defines the flow from an abstract viewpoint and the subclasses implement them appropriately. In your case, the simplest options are to either just leave performTransform empty in the superclass or implement it as an empty method in the subclass that doesn't require it (when you mix this approach with a short comment, you get a more maintainable system IMO).
The closest pattern I can think of for this is the Null Object pattern where this performTransform method is just a dummy function to preserve compatibility but perform no actual task.
Just because you say your bicycle is a car doesn't mean there's a place to put gas in it. The whole point of polymorphism is to let you think of things as the super class - these are all bank accounts, these are all shapes, to use the classic examples - and not get caught up in what they really are. Sometimes the subclasses add capability. In many cases that capability is used in the specific implementations in each subclass. So to use your names, some method Adjust() that is in the signature of SuperClass is implemented (differently) in SubClassA and SubClassB. The SubClassA version calls its own performTransform as part of the process and we all live happily ever after. The minute some code needs to decide whether to call performTransform or not, you're not just thinking of it as a SuperClass any more. That's not necessarily something that needs to be solved, it's just what is.
It Would be better to have the call to performTransform() in a method that only takes type SubClassB as a parameter - at least you wouldn't have to do type checking then.
On saying that, if your having this problem at all it may suggest that inheritance may not be the best solution - composition may be a better way to approach the problem.