Interface vs Inheritance

Monkey Forums/Monkey Programming/Interface vs Inheritance

c.k.(Posted 2012) [#1]
OOP newb question:

What are the benefits of an interface vs inheritance, besides the "promise to provide this method?" When would you choose one over the other?


Samah(Posted 2012) [#2]
You would choose inheritance if your class needs to inherit a lot of functionality, or if it makes sense to (eg. it makes more sense for Enemy to extend Unit).

You would choose an interface if your class already inherits a lot of functionality from another class, but needs to do "a bit more", and it doesn't make sense to put it in the parent class.


Gerry Quinn(Posted 2012) [#3]
C++ has a concept called multiple inheritance, in which a class inherits from more than one class. This can be useful, but can also get your code in a tangle when (for example) you have fields of the same name in more than one base class.

Interfaces are like multiple inheritance except you just inherit the function names. That means you don't save on coding (in fact you do extra) but it can aid in understandability of code. More typing but less head-scratching.

Now when a class is clearly derivative of another and replicates a ton of the same functionality, inheritance is the way to go. In Monkey (and most languages) you are limited to inheriting from just one class. If you want to have the same functions as several different 'classes', all but one of them must be interfaces. It's rarely a problem, and you can find other ways around the issue if you need to.


Rixarn(Posted 2012) [#4]
I would disagree with Quinn in the way to go for inheritance. Always favor composition (i.e. having a member object of the class you want to inherit) over inheritance. Inheritance is the way to go if you need polymorphism. That's pretty much the rule of thumb. If you're not using/need polymorphism with that class, then you should go for composition.


Tibit(Posted 2012) [#5]
My rule of thumb has started to go towards make it simple. If you truly do not need inheritance, do not use it.

If you do not need interfaces, do not use them.

Tough with that said, they are both very useful concepts but usually only when used by an experience programmer and a clear intent.

So my advice is, aim too:
1. Avoid inheritance unless you need polymorpism - it will most likely complicate your code
2. Avoid polymorphism unless it actually simplifies your code or reduces dependencies
3. If you need polymorphism use Interfaces, not Inheritance!
4. Avoid Interfaces unless they would help you reduce dependencies, simplify or help you test your code

I'm not sure there is a Interfaces vs Inheritance question, since you always use Interfaces if you can, and if you "can't" it is because your base class contains logic that you want to override in your sub-class, like the App class. Tough to be honest I'm not sure such an use case even exists. Even the App class would probably be better of if it used Interfaces, but also remember it was created before Monkey had interfaces :)

However sometimes it is easier to think in terms of "A inherit B" instead of using interfaces, and that is a reason - but it probably won't result in high quality code.


marksibly(Posted 2012) [#6]
Hi,

Interfaces are probably preferred where possible, as they allow for a form of multiple inheritance - ie: a class can inherit from more than one super class. This is nice because it means that when you design your classes, you don't have to limit yourself to a single 'root' class - you can tack on extra super classes anywhere down the inheritance chain.

On the downside, not being able to provide implementation code in interfaces limits where you can use them - you can't even provide simple helper methods that don't use fields or anything. And the bigger an interface gets, the more painful it is for clients to implement as they must implement ALL the methods. I remember hating Java for forcing me to have to write a bunch of NOP methods whenever I implemented WindowListener just to be able to detect window close!

But I think in general, any time you've got a class that contains only abstract methods designed to be implemented by subclasses, it's worthwhile thinking about converting it to an interface.


therevills(Posted 2012) [#7]
I was taught the following with inheritances and interfaces:

* Inheritance: "is a"

For example "Car is a Vehicle", "Class Car Extends Vehicle"

* Interfaces: "works like"

For example "Circle works like a Shape", "Class Circle Implements Shape" and different shapes will have to be drawn but they have to be drawn differently:

[monkeycode]
Strict

Import mojo

Function Main:Int()
New MyGame()
Return 0
End

Class MyGame Extends App
Field shapeList:List<Shape>

Method OnCreate:Int()
SetUpdateRate(30)
shapeList = New List<Shape>
shapeList.AddLast(New Circle(100, 100))
shapeList.AddLast(New Square(200, 100))
Return 0
End

Method OnUpdate:Int()
Return 0
End

Method OnRender:Int()
Cls
For Local s:Shape = Eachin shapeList
s.Draw()
End
Return 0
End
End

Interface Shape
Method Draw:Void()
End

Class BaseObject
Field x:Float, y:Float

Method New(x:Float, y:Float)
Self.x = x
Self.y = y
End
End

Class Circle Extends BaseObject Implements Shape
Method New(x:Float, y:Float)
Super.New(x, y)
End

Method Draw:Void()
DrawOval x, y, 20, 20
End
End

Class Square Extends BaseObject Implements Shape
Method New(x:Float, y:Float)
Super.New(x, y)
End

Method Draw:Void()
DrawRect x, y, 20, 20
End
End[/monkeycode]


ziggy(Posted 2012) [#8]
What therevils and Mark said. I would add, whenever you need to copy&paste the implementation of a given method of an interface, maybe it would have been better to use inheritance. Code redundance is a source of maintenance-time bugs.


Samah(Posted 2012) [#9]
Mark:
http://docs.oracle.com/javase/6/docs/api/java/awt/event/WindowAdapter.html

If the NOP methods annoy you, perhaps you could add optional methods like in Objective-C's @protocol? ;)
Edit: I managed to add an Optional keyword and generate default method implementations, but I couldn't get it to add a default return value once the classes had been "finalized".


Dima(Posted 2012) [#10]
Considering that Monkey supports reflection - would it be possible in theory to hot swap interfaces or even aggregate them at run time?