You can do
module Foo
attr_accessor :var
def initialize(*a,&b)
@var = 10
end
end
And then
irb(main):015:0> class Bar
irb(main):016:1> include Foo
irb(main):017:1> end
=> Bar
irb(main):018:0> Bar.new.var
=> 10
Or
irb(main):026:0> class Oink
irb(main):027:1> include Foo
irb(main):028:1> def initialize
irb(main):029:2> super
irb(main):030:2> @x = 10
irb(main):031:2> end
irb(main):032:1> end
=> nil
irb(main):033:0> Oink.new.var
=> 10
You have to be careful here, since it relies on invoking super in the
initialize method, and since the initialize method in the module
doesn't do this, it can break under the right conditions:
Absolutely!
class A
attr_reader :a_var
def initialize
@a_var = :a_var
end
end
module M
attr_reader :m_var
def initialize
@m_var = :m_var
end
end
class B < A
include M
end
B.new.instance_variables # => ["@m_var"]
Note that the A instance didn't get an @a_var instance variable.
The solution here is to invoke the superclass' initialize, which also
works for subclasses which don't have an initialize method themselves:
class A
attr_reader :a_var
def initialize
@a_var = :a_var
end
end
module M
attr_reader :m_var
def initialize
super
@m_var = :m_var
end
end
class B < A
include M
end
class C
include M
end
B.new.instance_variables # => ["@a_var", "@m_var"]
C.new.instance_variables # => ["@m_var"]
But this is hard to do in general when the initialize methods take
different parameters.
Well, as long as you make it a convention to do this in modules
def initialize(*a,&b)
super
# more
end
or have no #initialize in modules and make any class pass the proper super according to its superclass. I for my part would even opt to apply the following changes to the language:
1. ignore all arguments to a module's initialize
2. automatically do a super in module constructors which passes on the arguments passed by the class's constructor.
In other words: keep invocation of a module's initialize in the call chain but automate it to an extend that only class initialize pass on data to their superclasses. At least it seems the language has some room for improvements in this area. But then again, people do seem to rarely stumble across this, or do they?
module M
attr_reader :m_var
def initialize(*a, &b)
super
@m_var = :m_var
end
end
class D
include M
def initialize(d_val)
@d_var = d_val
super
end
end
D.new(10).instance_variables # =>
# ~> -:13:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
# ~> from -:13:in `initialize'
# ~> from -:30:in `initialize'
# ~> from -:35:in `new'
# ~> from -:35
But this will also break without the module because Object does not accept arguments to #initialize.
Kind regards
robert
···
On 13.02.2008 14:37, Rick DeNatale wrote:
On 2/12/08, Robert Klemme <shortcutter@googlemail.com> wrote: