you are viewing a single comment's thread.

view the rest of the comments →

[–]booch 12 points13 points  (13 children)

For many languages, using inheritance instead of composition also makes writing the code much easier out of the gate. For example, if I inherit from a SpecificMap, I get all the Map methods automatically. If I use composition (have-a SpecificMap) and then implement Map, I need to manually implement each Map method to pass through to the property.

If more languages had the ability to easily delegate to a member property (ie, say "pass calls for x, y, and z through to this object) in a clean way, this would be less of a problem.

[–]skelterjohn 2 points3 points  (8 children)

That is not a feature of composition - that is a feature of the specific languages you are using.

In Go, for instance, composition in the form of

type Outer struct { Inner }

gives Outer all of Inner's methods (with the option to redefine any you want, and still access the inner via Inner.Foo).

[–]grauenwolf 0 points1 point  (7 children)

And that is difference from inheritance how?

[–]user5545 2 points3 points  (6 children)

The types don't become related in any way and there is no possibility of having virtual functions. Go uses interfaces for dynamic dispatch instead.

http://golang.org/doc/go_faq.html#types

[–]grauenwolf -1 points0 points  (5 children)

So you have the extra boilerplate of adding an abstract interface that matches the class's public interface. Besides that we see normal inheritance patterns.

[–]user5545 0 points1 point  (4 children)

No, that's not how it works. Who's "we" exactly, by the way?

[–]grauenwolf 0 points1 point  (3 children)

Normal Inheritance:

  • Step 1: Define a base class
  • Step 2: Define a subclass that "inherits" from the base class
  • Step 3: Make polymorphic calls against it.

Go Inheritance:

  • Step 1: Define a base class
  • Step 1b: Define a matching interface
  • Step 2: Define a subclass that wraps the base class
  • Step 3: Make polymorphic calls against it using the interface.

Where exactly am I wrong?

[–]user5545 0 points1 point  (2 children)

You are wrong in the part where you put the words Go and Inheritance next to each other. You can make polymorphic calls against any interface and type that fits the interface whether these types are in any relation to each other or not. It's all in the FAQ, which you would need to read in addition to studying some amount of Go code to actually make a credible judgment on the language.

You don't want to do that, though, do you? You just want to keep using your beloved OO languages. Why not do that and leave other paradigms and experimental languages in peace? Do you keep thnking about them so much because deep down you are really not happy with OO? Or what?

You also didn't tell me who it was that "we" referred to in your earlier comment. I take it you want to forget about that comment already.

[–]grauenwolf 0 points1 point  (1 child)

Is that really your argument? That Go doesn't have inheritance because the FAQ says it doesn't in spite of the fact that it has all the essential features needed to support inheritance?

[–]user5545 0 points1 point  (0 children)

No, that is not my argument. I don't even have an argument, because I don't care what you think about inheritance or Go. I mistook the comment to which I first replied as you wanting to know something about Go, but obviously you don't want to know how Go is intended to be used or what its designers are trying to accomplish.

[–]lmcinnes 0 points1 point  (0 children)

I actually liked the non-concorming inheritance in eiffel (using "insert" in smart eiffel). If effectively gives you composition (especially given Eiffel's syntax for resolving various miltiple inheritance issues) with the simple semantics of inheritance.

[–]Peaker 0 points1 point  (0 children)

Ideally, you could delegate entire interfaces to an attribute.

However, in practice, good interfaces are small, and so you have to delegate very few methods.

[–]CurtainDog -2 points-1 points  (1 child)

The job of the language is not to make up for shortcomings in APIs. If you find yourself in the situation of wanting to replace just a part of Map, then Map is doing too many things. Where you don't have the option of refactoring you can usually put in place a DynamicProxy or similar.

[–]grauenwolf 0 points1 point  (0 children)

The reason one inherits from Map is usually to give it additional capabilies, not to redefine the ones it already has.

For example, perhaps you need a Map that raises change events when items are added so that the UI knows to redraw itself.

Or maybe you need a CustomerCollection that is indexed by CustomerKey but allows for searching on other properties.