views:

98

answers:

3
A: 

I think you should not take decision on base of some sort of rumors. Sometimes composition is really good, but it require more code writing and more difficult in support (if you change BasicLight interface, you should manually change all dependent classes). Inheritance solve this problems, and some others. There are some cases when composition is preferable, but they appear mostly in complex projects.

Tiendil
+4  A: 

OK, there are a few things to cover here.

First: why do you need to express commonality between PointLight and Spotlight? Is it

  1. Because there are clients who simply want to use them as a Light, and don't care which variety they get?
  2. Because they share some implementation and you don't want to duplicate?

Because Clients need to treat Lights uniformly

This is Interface inheritance, also known as subtyping. Composition doesn't apply here - because there's nothing to compose. You can realise this in two ways: which you choose depends largely on your language.

  • If you're using Java/C# this would usually be achieved by defining an Interface (ILight) that exposes all the common characteristics of Lights. Clients would depend only on the interface, not the implementations of it. PointLight and SpotLight would each implement the interface.
  • If you're not using a language with first class Interfaces, declare Light as an abstract base class with PointLight and SpotLight inheriting from it.

Because you want to share implementation

There are generally two approaches to achieving this:

  • Implementation inheritance. Define class Light and implement common behaviour in it. Declare PointLight and SpotLight as inheriting from Light, overriding/adding behaviour as required.
  • Composition. Define classes PointLight and SpotLight without inheriting from a common superclass. Implement a third class (which you'd still probably call Light) that implements the common behaviour. Both PointLight and SpotLight would include an instance of 'Light` and delegate to it for the shared behaviour.

For your specific example there's relatively little to choose between Implementation inheritance and Composition. Issues with the former arise when the inheritance hierarchy gets deeper. It's also notoriously error prone in languages that support multiple implementation inheritance (e.g. the fragile base class problem). On the other hand, Implementation inheritance means less typing: the language autoamtically delegates to the shared behaviour, whereas with Composition you need to write the delegation methods.

Summary

Note also the above are not mutually exclusive: you could, for example:

  • Declare an Interface ILight that both SpotLight and PointLight implement
  • Share common behaviour using either implementation inheritance or composition

Fundamentally you need to be clear what you're trying to achieve.

hth.

sfinnie
Thanks for a great answer! I think my main taught about this was to achieve a bit of both from your main points. Lights are treated equally in a container, and I want to share some implementation between the lights, methods like set_position() for example.
Morgan
No worries. Shout if you need more info.
sfinnie
+1  A: 

I think you should look at component based design. Take a look at this, the top answer has some great resources.

Spiphy