How to make a given klass to include a module

Hi, simple code:


module M
def hello
“HELLO”
end
end

class A
end

klass = A

Now I want to make an instance of klass (so an instance of A) but also
need that klass includes module M.
Note however that I cannot change class A definition since klass is
given in runtime by the user.

NOTE: It must be efficient, I don’t want to use eval and so.

Thanks a lot.

Am 09.05.2012 13:36, schrieb Iñaki Baz C.:

end
NOTE: It must be efficient, I don’t want to use eval and so.

Thanks a lot.

ruby -v: ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

irb(main):001:0> module M
irb(main):002:1> def hello
irb(main):003:2> “HELLO”
irb(main):004:2> end
irb(main):005:1> end
=> nil
irb(main):006:0> class A
irb(main):007:1> end
=> nil
irb(main):008:0> klass = A
=> A
irb(main):009:0> klass.send(:include, M)
=> A
irb(main):010:0> a = klass.new
=> #<A:0x0000000202cfe0>
irb(main):011:0> a.hello
=> “HELLO”

Alternatively, if you don’t want to pollute the given class, use #extend
on the instances (which is also more clean as it doesn’t require #send).

Vale,
Marvin

2012/5/9 Quintus [email protected]:

=> A
irb(main):009:0> klass.send(:include, M)
=> A
irb(main):010:0> a = klass.new
=> #<A:0x0000000202cfe0>
irb(main):011:0> a.hello
=> “HELLO”

Alternatively, if you don’t want to pollute the given class, use #extend
on the instances (which is also more clean as it doesn’t require #send).

Great!

I’ve tested that first option is much faster (more than 10 times
faster) than extending each instance, so I’ll go with first solution.

Thanks a lot.

Thanks a lot.

On Wed, May 9, 2012 at 1:52 PM, Iaki Baz C. [email protected] wrote:

on the instances (which is also more clean as it doesnt require #send).

Great!

I’ve tested that first option is much faster (more than 10 times
faster) than extending each instance, so I’ll go with first solution.

Maybe also add an additional test:

irb(main):001:0> class A;end
=> nil
irb(main):002:0> module M; def hello; “hello” end end
=> nil
irb(main):003:0> M===A || A.send(:include, M)
=> A
irb(main):004:0> A.new.hello
=> “hello”

Cheers

robert

On Wed, May 9, 2012 at 4:32 PM, Iaki Baz C. [email protected] wrote:

=> “hello”
MMM===AAA
=> false

Stupid me, should’ve tested better. I confused that with the instance
check. Sorry for the confusion.

I meant “A < M”:

irb(main):008:0> class A; end
=> nil
irb(main):009:0>
irb(main):010:0* module M; end
=> nil
irb(main):011:0> A < M
=> nil
irb(main):012:0> A.send :include, M
=> A
irb(main):013:0> A < M
=> true

So it’s

A < M || A.send(:include, M)

Kind regards

robert

Iñaki Baz C. [email protected] wrote:

NOTE: It must be efficient, I don’t want to use eval and so.

Any time you modify a class/eigenclass (via include/extend), you lose
efficiency in MRI/YARV. The runtime needs to invalidate its internal
caches for method lookup whenever classes are modified.

2012/5/9 Robert K. [email protected]:

Maybe also add an additional test:

irb(main):001:0> class A;end
=> nil
irb(main):002:0> module M; def hello; “hello” end end
=> nil
irb(main):003:0> M===A || A.send(:include, M)
=> A
irb(main):004:0> A.new.hello
=> “hello”

Hi, I don’t get the point of that. M===A always returns false
regardless A includes M:

module MMM ; end

class AAA
include MMM
end

MMM===AAA
=> false

On Wed, May 9, 2012 at 6:36 AM, Iaki Baz C. [email protected] wrote:

end
NOTE: It must be efficient, I don’t want to use eval and so.

Thanks a lot.

Since we don’t want to change A, use a subclass. It will have all the
behaviour of A, but you can include modules and so forth while leaving M
in
pristine condition.

klass = Class.new(A) { include M }
klass.new.hello # => “HELLO”
A.new.respond_to? :hello # => false

Alternatively, extend your instances:

klass = A
instance = klass.new
instance.extend M
instance.hello # => “HELLO”
A.new.respond_to? :hello # => false

Extending works by opening up the singleton class and including within
it.
This means the instance behaves as if A had M included, even though it
doesn’t.

2012/5/9 Eric W. [email protected]:

Iñaki Baz C. [email protected] wrote:

NOTE: It must be efficient, I don’t want to use eval and so.

Any time you modify a class/eigenclass (via include/extend), you lose
efficiency in MRI/YARV. The runtime needs to invalidate its internal
caches for method lookup whenever classes are modified.

Good to know. But if the “include” is added during the class
definition there is no efficiency loss, am I right?:

class A
include M
end