Project

General

Profile

Actions

Feature #11550

open

Current behaviour of super(...) is dangerous in the presence of more than one included modules.

Added by rovf (Ronald Fischer) over 8 years ago. Updated about 8 years ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:<unknown>]

Description

Consider a class

   class C <P
     include M1
     include M2
     def initialize
       ....
     end
   end

If P, M1 and M2 all provide a initialize method, and C::initialize calls super(...), the first initialize module in the chain, which has a formal parameter list matching the actual parameters in the super(....) call, is executed. The other ones are not executed. The following article demonstrates a clever way, how C::initialize can call all initializers of the included modules and of the parent class:

[[http://stdout.koraktor.de/blog/2010/10/13/ruby-calling-super-constructors-from-multiple-included-modules/]]

This solution works, but is complicated, and the reason is that the basic design of Ruby, with respect of initializing the base class, is flawed, for the following reason:

If we define an 'initialize' method, we certainly assume that its execution is necessary for the correct behaviour of our class or module. Therefore, the designer of a class or module should at least have the possibility to REQUIRE that initialize will be called (by a derived class), and the designer of a class which inherits from a parent class or includes a module, should have an EASY way to call all the parent initializers.

Here a first draft of how the language could be changed to meet this criterium; it's perhaps not the best design, but it might help clarifying my point:

(1) A class (or module) may define either a method initialize or a method initialize_strict (but not both). If it has initialize_strict defined, and the class where the module is included, respectively the class which inherits it, does NOT invoke this initializer, an exception is thrown, UNLESS initialize_strict can be called without parameters. In the latter case, it is always executed (even if no 'super' call is present).

(2) A class method super_of is added to class Object, with the prototype super_of(klass,arg*), where klass is a symbol or String or instance of type Class or Module. The affect of invoking super_of(:Foo,x,y) is identical to invoking initialize(x,y) in the ancestor class Foo. If Foo is neither a direct ancestor nor an included module, an exception is thrown.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0