mysterious behavior of mixins

I

i3dmaster

I am trying to learn how mixins are behaved and encountered a strange
behavior and got me even confused...

irb(main):151:0> module A
irb(main):152:1> def self.showself
irb(main):153:2> puts "self is #{self.inspect}"
irb(main):154:2> end
irb(main):155:1> def showself
irb(main):156:2> puts "self is #{self.inspect}"
irb(main):157:2> end
irb(main):158:1> end
=> nil
irb(main):159:0> A.showself
self is A
=> nil
irb(main):160:0> class B
irb(main):161:1> include A
irb(main):162:1> end
=> B
irb(main):163:0> B.showself
self is B
=> nil
irb(main):164:0> B.new.showself
self is #<B:0x4ce78>
=> nil
irb(main):165:0> class C
irb(main):166:1> def self.showself
irb(main):167:2> puts "in C's showself"
irb(main):168:2> end
irb(main):169:1>
irb(main):170:1* end
=> nil
irb(main):171:0> class B < C
irb(main):172:1> include A
irb(main):173:1> end
TypeError: superclass mismatch for class B
from (irb):171
from :0

Then I tried another several times and it always throws out TypeError,
then I tried this:

irb(main):022:0> class D
irb(main):023:1> include A
irb(main):024:1> end
=> D
irb(main):025:0> D.showself
NoMethodError: undefined method `showself' for D:Class
from (irb):25
from :0
irb(main):026:0> ^C
irb(main):026:0> quit

I was able to minxin A's class method (using class B) just a moment
ago. What the heck is going on? Questions:
Does mixins allow mixin class methods or not? If not, what's the
common idiom to mixin class methods?
Is there a concept of protected or private mixins? I see mixins be
able to just mixed in with arbitrary classes. Is there possible to
force some certian mixins only be able to be mixed in with a certain
classes or other modules?
 
T

Trans

I am trying to learn how mixins are behaved and encountered a strange
behavior and got me even confused...

irb(main):151:0> module A
irb(main):152:1> =A0 def self.showself
irb(main):153:2> =A0 =A0 puts "self is #{self.inspect}"
irb(main):154:2> =A0 end
irb(main):155:1> =A0 def showself
irb(main):156:2> =A0 =A0 puts "self is #{self.inspect}"
irb(main):157:2> =A0 end
irb(main):158:1> end
=3D> nil
irb(main):159:0> A.showself
self is A
=3D> nil
irb(main):160:0> class B
irb(main):161:1> =A0 include A
irb(main):162:1> end
=3D> B
irb(main):163:0> B.showself
self is B

Are you sure about this? Ruby doesn't do that. (Which I've never been
completely happy about, but that's another story...)
=3D> nil
irb(main):164:0> B.new.showself
self is #<B:0x4ce78>
=3D> nil
irb(main):165:0> class C
irb(main):166:1> =A0 def self.showself
irb(main):167:2> =A0 =A0 puts "in C's showself"
irb(main):168:2> =A0 end
irb(main):169:1>
irb(main):170:1* end
=3D> nil
irb(main):171:0> class B < C
irb(main):172:1> =A0 include A
irb(main):173:1> end
TypeError: superclass mismatch for class B
=A0 =A0 =A0 =A0 from (irb):171
=A0 =A0 =A0 =A0 from :0

Then I tried another several times and it always throws out TypeError,
then I tried this:

irb(main):022:0> class D
irb(main):023:1> =A0 include A
irb(main):024:1> end
=3D> D
irb(main):025:0> D.showself
NoMethodError: undefined method `showself' for D:Class
=A0 =A0 =A0 =A0 from (irb):25
=A0 =A0 =A0 =A0 from :0
irb(main):026:0> ^C
irb(main):026:0> quit

I was able to minxin A's class method (using class B) just a moment
ago. What the heck is going on? Questions:
Does mixins allow mixin class methods or not? If not, what's the
common idiom to mixin class methods?
Is there a concept of protected or private mixins? I see mixins be
able to just mixed in with arbitrary classes. Is there possible to
force some certian mixins only be able to be mixed in with a certain
classes or other modules?

Look into Module#included and Module#append_features. Eg.

module X
def self.included(base)
base.extend MetaX
end

module MetaX
# class method here
end

extend MetaX
end

T.
 
T

Thomas B.

Jim said:
irb(main):171:0> class B < C
irb(main):172:1> include A
irb(main):173:1> end
TypeError: superclass mismatch for class B
from (irb):171
from :0

Of course you cannot do it, because a moment ago you declared the method
B as an immediate descendant of Object, and now you want it to be the
descendant of C. The error has nothing to do with mixins.

irb(main):046:0> class A;end
=> nil
irb(main):047:0> class B;end
=> nil
irb(main):048:0> class B<A;end
TypeError: superclass mismatch for class B
from (irb):48
 
I

i3dmaster

Are you sure about this? Ruby doesn't do that. (Which I've never been
completely happy about, but that's another story...)







Look into Module#included and Module#append_features. Eg.

  module X
    def self.included(base)
      base.extend MetaX
    end

    module MetaX
      # class method here
    end

    extend MetaX
  end

T.

I know that's why I am quite confused about this. the ruby-doc really
didn't clearly say that class methods can't be mixed in.

"Ruby‘s default implementation is to add the constants, methods, and
module variables of this module to mod if this module has not already
been added to mod or one of its ancestors"

Is there an violation for mixing in class methods from module?
Conceptually, I can't think of one though.
 
I

i3dmaster

Of course you cannot do it, because a moment ago you declared the method
B as an immediate descendant of Object, and now you want it to be the
descendant of C. The error has nothing to do with mixins.

irb(main):046:0> class A;end
=> nil
irb(main):047:0> class B;end
=> nil
irb(main):048:0> class B<A;end
TypeError: superclass mismatch for class B
        from (irb):48

Yes, my mistake. I am still trying to get comfortable that Ruby allows
extending existing classes in runtime... I always thought that when
defining a new class, it points the symbol to a new object instead of
opening up the existing object... (under the same scope of course)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top