How do I change the mixed-in method at runtime ?
Also, is the mixin class-level or object-level? 


Peter J. Fitzgibbons
Applications Manager
Lakewood Homes - "The American Dream Builder"(r)
Peter.Fitzgibbons / Lakewoodhomes.net
(847) 884-8800 


-----Original Message-----
From: Dave Burt [mailto:dave / burt.id.au] 
Sent: Thursday, August 11, 2005 4:21 PM
To: ruby-talk ML
Subject: Re: Head First Design Patterns - Strategy Pattern [was: Java/C#
"interface" in Ruby ?]

Peter Fitzgibbons wrote:
> ...
> My question is this: The :quackDelegate and :flyDelegate are written 
> in Java/C# as object instances of an interface.  Clearly I've ditched 
> the interface itself, but the rest is pretty much as described in the
book.

This looks like exactly what mixins are for - you can put the
implementation itself in a module and then include it rather than using
delegation and having extra objects with one-method floating around.

class Duck
  def swim() "All ducks float, even decoys!" end end

module FlyWithWings
  def fly() "I'm flying!" end
end

# other Flys and Quacks as above, the only change is class -> module...

class MallardDuck < Duck
  include Quack
  include FlyWithWings
end

class ModelDuck < Duck
  include FlyNoWay
  include Quack
end

# next file, duck_test.rb
require 'test/unit'
require 'duck'

class DuckTest < Test::Unit::TestCase
  def testMallard
    mallardDuck = MallardDuck.new
    assert_equal "Quack", mallardDuck.quack  # no intermediate method
needed
    assert_equal "I'm flying!", mallardDuck.fly
  end

  def testModelDuck
    modelDuck = ModelDuck.new
    assert_equal "Quack", modelDuck.quack
    assert_equal "I can't fly", modelDuck.fly
    modelDuck.extend FlyRocketPowered
    assert_equal "I'm flying Rocket Powered!!", modelDuck.fly
  end

end

And there you have it - much nicer!

If you do want to use delegation (I don't know why), you can use a class
with a single class- (like Java static-) method; then you don't need to
use FlyWithWings.new, you just pass the FlyWithWings class:

class FlyWithWings
  def self.fly() "I'm flying!" end
end
# ... (only changes are "def fly()" -> "def self.fly()") class
MallardDuck < Duck
  def initialize
    @flyDelegate = FlyWithWings
# ... (only changes are "= FlyWithWings.new" -> "= FlyWithWings")

Cheers,
Dave