Aren't we breaking the Single Responsibility Principle with this super-mega-god-interface?
Not exactly, because the interface isn't doing anything. It has no responsibilities.
You are breaking Liskov Substitution Principle and Interface Segregation Principle though.
LSP because you're writing methods that do nothing, just to make it fit the interface (ie. What is true of IDrawable -- that you can move it -- is not true of Wall).
ISP because you'll have situations like a trade method, which should have access to Buy and Sell methods, but will also have access to Draw.
Are both approaches valid against the Liskov's Substitution Principle? I think it's broken in the first case because the post-conditions are broken due to some methods don't do anything. Anyway, in the second approach I'm not sure as well because of the interfaces inheritance tree
It's just as broken in the second case as the first.
Edit: On second thoughts, it isn't. But it is still broken. It doesn't seem automatically true that everything that could have a Move method will also have a Draw method. It might be true in your case but, if you later find yourself wanting to pass an object with a Move method into a method that receives an IMovable, you're going to have to implement Draw on that object, even if you don't need it.
And it gains you nothing over a third solution ...
Maybe, another alternative could be the definition of basic Drawable objects (with 'click' and 'draw' methods). Thus, we may take advantage of some kind of mechanism like the Decorator pattern in order to add behaviors dynamically. But how?
The best alternative is to segregate your interfaces fully. You can still have objects with lots of methods (but Dependency-Inversion Principle and Single Responsibility Principle dictate you must push the logic down into services), but they only have to implement the interfaces they need. Wall shouldn't implement IMovable, if it can't be moved.
public class Wall : IDrawable
public class Furniture : IDrawable, IMovable, ISellable
public class Window : IDrawable, IOpenable
Nothing here dictates that any of those interfaces must derive from another.
public interface IDrawable
{
void Draw(Canvas canvas);
}
public interface IMovable
{
void MoveTo(int x, int y);
}
etc
You should then manage your list of IDrawables, which you can only be sure implement Draw(), and cast to see if other methods are available.
For example,
ITradable tradable = drawable as ITradable;
if (tradable != null)
{
tradable.Trade(buyer, seller);
}
You're going to have to do the above in your option 2 anyway, so why tie everything to IDrawable?
If we use a language without interfaces such as JavaScript or Python, how can we deal with this problem?
OO languages tend to support at least one of three things:
Prototypical languages, such as Javascript, support ... well, prototypes, which allow for a slightly modified version of duck-typing (in prototypes, you generally ask if a method exists before calling it).
Other paradigms generally handle these issues in their own way.
This is not only bad practice, this is unnecessary complicated.
Why do you use inheritance in general?
When you use inheritance, you have a common set of behaviour, which you want to make available for many different carriers. This includes class inheritance as well als interface inheritance. The heir, so to speak, is oftentimes a specialization of the class from whom it inherits; which is mainly true for class inheritance.
Think of a class car and a subclass porsche (the typical is a-relationship). You have general behaviour like starting/stopping engine, steering and so on. If you treat a porsche like a car, you are bound to this aspect of its behaviour. If you know, that you only want a porsche and only deal with it as a porsche, it is redundant to instantiiate a porsche as a car and get porsche-behaviour via casting.
Polymorphism makes sense the other way around:
You have a porsche and need to treat it from the aspect of a car; e.g. driving
As long as your porsche accepts steer left, steer right, shift up, shift down, etc. you could make use of polymorphism/substitution one for the other.
It is better, to instantiate your objects in their specialized form. Then you could make the most of polymorphism and use it only when you need it.
That said: Parent p = new Child1();
makes no sense for me.
Edit: I would implement porsche different (via composition), but for the sake of the example, it is a car.
Best Answer
Single dispatch is somewhat easier to implement, and multiple dispatch is rather rarely needed in practice according to research by Muschevici et al.
You can find more information in the Wikipedia article on multiple dispatch; for instance, it also explains why the CLOS method of defining multimethods may be a better fit for Lisp's extremely uniform syntax, rather than for the more prevalent nesting of methods within classes.