Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.
Many people hear about Ruby mixins, but don't actually know what they are since they don't program in Ruby. Plus, I see a number of questions online about how to write a mixin in Ruby. So here's a quick example for Perl programmers to see how it's done (note: I'm hardly a Ruby guru, so be forewarned).
To use mixins in Ruby, first create modules with the behavior you want to share. A module can be thought of as an incomplete class which you cannot instantiate.
module Bomb
def explode
puts "Bomb explode"
end
def fuse
puts "Bomb fuse"
end
end
module Spouse
def explode
puts "Spouse explode"
end
def fuse
puts "Spouse fuse"
end
end
Then in your class, simply include the mixins:
class PracticalJoke
include Spouse
include Bomb
end
So what does that do?
joke = PracticalJoke.new()
joke.explode
joke.fuse
This nicely allows classes to simply be responsible for generating instances and shared behavior is handled by the mixins. Unfortunately, that prints:
Bomb explode
Bomb fuse
In other words, we've exchanged multiple inheritance's "first wins" behavior with mixin's "last wins" behavior. Trying to get one method from each appears to need delegation.
Also, I've noticed that it appears that you're not flattening these methods into your class, as you would with roles, but are instead inheriting from the mixins:
irb(main):026:0> PracticalJoke.ancestors
=> [PracticalJoke, Bomb, Spouse, Object, Kernel]
This means that your mixin methods aren't really getting "mixed in" to your class. I'm not sure of the downside of this (aside from having a longer inheritance chain), but the upside is that you can at least override methods cleanly:
class PracticalJoke
include Spouse
include Bomb
def explode
puts "PracticalJoke explode"
end
end
joke = PracticalJoke.new()
joke.explode
joke.fuse
And joke.explode will print PracticalJoke.explode. I think this means that if you want a warning at the PracticalJoke level about an accidental override, you're out of luck.
Further comments from Ruby experts welcome.
Why? (Score:1)
Re: (Score:2)
It's easy for this to happen, particularly in large systems. Here's what I'm working on right now:
And we're still adding roles.
When you have a large system with multiple roles, it's likely that you'll eventually encounter situations where roles provide similarly named methods. This should generally only happen if these methods are semantically equivalent, but provide different implementations. As just one exam
Re: (Score:1)
Using a thing like the Ruby mixins for such cases is over the top.
The programming God tells me one should use simple delegation for such cases like they do in Cocoa (and it looks simple and beautiful).
Re: (Score:2)
Delegation is great, but when the thing delegating and the thing being delegated to need to communicate with one another, you start winding up with problems. We already have components (roles) that we can assemble and need to work well together and separating them out via delegation means a separate class heirarchy just have to have something to delegate to. Why would I want to write the scaffolding for delegation? Honestly, roles are really, really simple and make this trivial :)
Plus, delegation is for
Proxies (Score:1)
Pickaxe Book (Score:1)
According to the Pickaxe book (figure 18.4) [skitch.com] (page 247 of the first edition). Mixins modules are actually proxied. You can see in the diagram that it inserts a Proxy class between Guitar class and the Object class. The Proxy class does not have any methods itself, but instead it has a pointer to the method table of the module it is proxying. This gets more and more ugly and complicated the more modules you mixin, however it does explain the odd "last wins" behavior.
Of course, I am not sure if this is stil
Mixins and Inheritance (Score:2)
http://www.chadfowler.com/2009/7/8/how-ruby-mixins-work-with-inheritance [chadfowler.com]