"Emiel van de Laar" <emiel / il.fontys.nl> schrieb im Newsbeitrag news:20040727111212.GA17548 / il.fontys.nl... > Greetings, > > Lately I've been pondering about the trade offs one must make when > implementing classes which maintain internal collections. My question > is, when is it wise to inherit and when to encapsulate. I've attached > some sample Ruby code to demonstrate my thinking. My current issues > are with C# but I believe it to be a general OO issue. > > Inheriting from collection classes, i.e. Array, Hash, is simple, fast > and takes relatively little code. However every method available is > exposed to the implementing class. Something we don't always want. > > Encapsulation(by association) prevents method pollution by exposing > only what is needed, which gives us more control. For code completion > this is nice because we aren't confronted with an excessive amount of > methods; we only see what is needed. > > Another benefit of encapsulation is that you can replace your internal > collection at a later stadium with an alternative implementation, > perhaps for performance reasons. As long as the interface to the > implementing class remains the same you are free to do as you > please internally. Basically you named all important arguments, so the conclusion is: use delegation. Even more so since it is so simple in Ruby (see below). Inheritance is almost always the wrong choice here. Bertrand Meyer, the OO guru and inventor of Eiffel, has a different approach to this: he prefers inheritance and calles it "implementation inheritance". But you need a language in which you can do it. The difference between Eiffel and other languages is that Eiffel allows to hide methods that you don't want accessible from the outside for a sub class instance. Personally I dislike that because that makes naming a inheritance relationship "is a" questionable, because the interface of the sub class is not a superset of the super class's interface and thus both are not compatible (see also "Liskov substitution principle"). > At times though, it can be a pain exposing all the methods we need; > sometimes we need them all. I know Ruby offers us the "method_missing" > feature which I have used a lot, however, as far as I know C# doesn't > offer me such a luxury. Think also of Delegator and SimpleDelegator, which make life even easier: require 'delegate' class ArrayFoo < DelegateClass(Array) def whatever_additional_method_you_need end end In certain cases (simple scripts) singleton methods may be sufficient, so you don't need to create a new class at all: numbers = (1..10).map { rand 10 } def numbers.max; inject(0){|m,i| i>m ? i : m} end puts numbers.max Kind regards robert