views:

334

answers:

6

First off, I know next to nothing about language theory, and I barely know any other languages except Java, but I had an idea that I think would be cool, but I need you guys to tell me:
a: why it sucks
b: how language x has had that for years
c: how my mind sucks
d: all of the above

The idea would give composition the same ease of code reuse that extends does.

So if you had a class like this:

public interface A {  
    public void methodInA();  
}

And then you had a class like this:

public class B {  
    private composed A;
    public B() {
        // construct A within constructor
    }
}

You would then be able to do this:

B myB = new B();
myB.methodInA();

Without having to add in the delegation in B's class. But you could also do the same as with inheritance, ie:

@Overrides
public void methodInA(){
    // B's own delegation method
}

Disadvantages include:

  • methods are hidden in the source code, making it less obvious where the call is coming from, but this is also the case with extends
  • if composed fields share the same method signature there needs to be a conflict resolved (how do conflicting interfaces solve this?)
  • if you wanted to have several composed fields of the same type, there would be an obvious conflict for which field to delegate to
  • probably 100 other things I've not thought of

Like I say, I'm obviously no language theorist, and I haven't spent ages thinking about it, the idea just popped in my head and I wanted to know how wrong I am. I just think it would be kind of cool.

+1  A: 

I'm not sure that I see a clear advantage to doing this though. I understand the point you are making. At the moment to call a method on A you have to myB.getAInstance().methodInA(), but you want to make that myB.methodInA().

But, what happens if you have multiple instances of A? How would the method call be resolved? Many times composition implies a one to many association so B has many A instances. What happens then?

I agree with your disadvantages listed. It may simply cause too much confusion than it is worth.

Vincent Ramdhanie
It's not exactly that I would want myB.getAInstance().methodInA(), I may be using the composed field to implement an interface, so the class must have the method itself.
Grundlefleck
Argh, I should re-read before I reply.
Grundlefleck
+2  A: 

It sounds cool but I think it makes for some horrible language constructs. Obviously there is a problem if you declare more than one 'composition' of the same class, but even if you forbid that what about the case where a call matches a method in more than one of the (different) composed classes? You would have to specify which one was called in the main class, and you would need extra syntax for that. The situation becomes even worse if there are public members in the classes.

Composition is used to prevent problems with multiple inheritance. Allowing composition like this is effectively permitting multiple inheritance, at least in terms of resolving which method to call. Since a key design decision with Java was to disallow multiple inheritance (for good reasons) I think it unlikely that this would ever be introduced to Java.

DJClayworth
"..I think it unlikely that this would ever be introduced to Java." - I hear that, if I can form the idea for an addition to one of, if not the most, widely used programming language, on what was quite a slow afternoon... well, we and Sun are in trouble :-D
Grundlefleck
What about, if the compiler found a conflict, it would force you to override it? So you are forced to resolve it in one single way, without too much of a syntax cost, as it wouldn't look out of place. But public members... yeah hadn't thought of them at all... hmmm.
Grundlefleck
A: 

There's also the difference between composition and aggregation to consider. How does the compiler know whether you mean 'is-a' or 'has-a' relationships?

  • Does the whole object graph become eligible for garbage collection or only the head of the graph?

A couple of the ORM mapping tools and frameworks over/around them provide for belongsTo or has-many relationships between persistent objects and some also provide for the cascading delete (for composition). I don't know of one off hand that provides the simple syntactic sugar you're looking for.

Actually, on second thought, Groovy's MetaClass and MetaProgramming idiom(s) may provide something very similar, with 'auto-magic' delegation.

Ken Gentle
A: 

Multiple inheritance is allowed in C++, I know that different but it is along the same thought process. Java was designed to not allow multiple inheritance so that there would be less confusion, therefore bugs and exploits.

What you have suggested is in direct conflict with the principles of java.

Having said that, it would be cool (not necessarily useful). I'm a java programmer who switched from C++. I like being able to make my own mistakes.

WolfmanDragon
+1  A: 

Check out what is called "Mixins" in some languages, and "Roles" in the Perl 5 Moose OO system.

skiphoppy
+1  A: 

I think if you restricted it such that a class could only use this feature to compose a single class it would be somewhat useful and would avoid a lot of the headaches that are being discussed.

Personally I hate inheritance of concrete classes. I'm a big proponent of Item 14 from Bloch's Effective Java, Favor composition over inheritence. I think that something like this would make it a little easier to implement the idiom he recommends in that item.

Honestly, if you really knew what you were doing I'll bet you could write a compiler annotation that would handle this. So assuming you had a class Bar that implemented the interface IBar, your class would look like this:

public class Foo {

  @Delegate(IBar.class)
  private Bar bar;

  // initialize bar via constructor or setter
}

Then during compilation Foo could be made to implement IBar and any of the methods on that interface that weren't already implemented by Foo would end up being generated to look like this:

public Baz method1(Qux val) {
  return bar.method1(val);
}

As mentioned above you would want to make the restriction that only one field per class could use this annotation. If multiple fields had this annotation you'd probably want to throw a compilation error. Alternatively you could figure out a way to encode some sort of precedence model into the parameters passed to it.

Now that I've written this out that seems kinda cool. Maybe I'll play around with it next week. I'll update this if I manage to figure anything out.

Mike Deck
"Honestly, if you really knew what you were doing..." - and therein lies the rub my friend! :-D
Grundlefleck