2

Say you have interfaces IBuilding and IDwelling, and class House which implements both. It encapsulates a building and a dwelling:

class House implements IBuilding, IDwelling { private IBuilding building; private IDwelling dwelling; } 

If IBuilding and IDwelling each define 15 methods, is it really normal to write 30 methods in the House class that just forward to the methods of the door or window?

That seems very, very tedious. Is this really a thing? A lot of resources indicate that, yes, that's what you'd do, but they all use super-simple examples that don't make it look as daunting as I imagine it would be in real life.

Or is there some smarter way to compose that I'm not aware of?

2
  • 1
    The code sample doesn't make sense to me. Why would the House encapsulate Building and Dwelling, especially when it already implements them? Is it just a bad example or it's Your real code? If the latter, I'd suggest that You consider redisigning Your system. Commented Dec 19, 2012 at 9:10
  • 2
    Sorry, yes, I wrote a bad example to try and illustrate it. My point was basically: Many people write a class which is composed of other classes; this class must expose many of the methods of the classes of which its composed; is it standard practice to write many individual "forwarder" methods that just wrap those of the inner classes? Commented Dec 19, 2012 at 18:04

2 Answers 2

2

Does it have to be this tedious? No. Is there any smarter way? Yes.

There are 3 reasons I can think of why You would use the composition:

  1. to establish a "has a" relationship between objects;
  2. to create some kind of a wrapper class (decorator/proxy);
  3. to bypass the single inheritance constraint, if it's applicable to Your language.

Of the three, only case #2 may require that You forward every call from Your wrapper class to the wrapped one. Even so, there are some languages that may allow You to create a so called "dynamic" proxy, so that You don't have to create a method in Your outer class for every method in Your inner class just to forward the call. For example, in Java it's called the Dynamic Proxy Class, in PHP it's the magic __call() method.

Another thing is that situations like the one You described in Your question are very rare in practice.

UPDATE

The main problem here is that while using PHP if we want the wrapper class to implement the wrapped class's interface, the __call() method, indeed, can't really help us. If the interface has few methods, it's not difficult to implement them, but what if it has 15? This problem, I believe, is not a problem of the composition, it's a problem of big interfaces. To avoid such problems You need to follow the Interface Segregation Principle. Sometimes, though, if You're writing a general purpose API it's hard to follow the principle. If this is the case, then there's nothing else left You can do except for one-to-one mapping of method calls. Sorry.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I considered PHP's __call, but then the class would not actually implement the interfaces without all the required methods actually defined.
Thanks, I find your response very helpful. I guess this is the kind of thing that mixins are meant to help with? Still,l it seems odd. We do away with multiple inheritance, saying it's bad and we should use interfaces. Then we say composition is better than inheritance. Then we bring in mixins to make situations like this easier. Then... seems like we're almost right back to multiple inheritance.
0

While it seems like an extreme example, yes, composition is about delegating horizontally and you have, most of the times, to explicitly program that delegation. Depending on the language that you are programming you may find Traits like a good mechanism to achieve horizontal composition without writing the "glue code". You may find the paper Traits: Composable Units of Behaviour a good read, explaining the problems of vertical reuse and why approaches like traits are an alternative.

HTH

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.