Created
October 31, 2008 03:07
-
-
Save audionerd/21209 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# A demonstration of Ruby mixins, in response to: | |
# http://www.deftflux.net/blog/post/A-good-design-for-multiple-implementation-inheritance.aspx | |
module BarkingBehavior | |
def bark | |
puts "Bark!" | |
end | |
end | |
module MeowingBehavior | |
def meow | |
puts "Meow!" | |
end | |
end | |
class Dog | |
include BarkingBehavior | |
end | |
class Cat | |
include MeowingBehavior | |
end | |
class Human | |
include MeowingBehavior | |
include BarkingBehavior | |
end | |
class NoisyHuman | |
include MeowingBehavior | |
include BarkingBehavior | |
def meow | |
puts "MEOW! MEOW! MEOW!" | |
end | |
def bark | |
puts "BARK! BARK! BARK!" | |
end | |
end | |
puts <<HEREDOC | |
> Mixin example: | |
HEREDOC | |
human = Human.new | |
human.bark | |
human.meow | |
puts <<HEREDOC | |
> A behavior would be implicitly abstract in that it could not be directly instantiated. | |
HEREDOC | |
begin | |
new MeowingBehavior | |
rescue => error | |
puts "Can't create an instance of MeowingBehavior" | |
end | |
puts <<HEREDOC | |
> Polymorphism would not apply to behaviors. Meaning that an implementing | |
> class could not be referenced as an object of a behavior. As a result, | |
> variable types, parameter types, etc. could not be behaviors. | |
> This would prevent the poor designs multiple inheritance would normally enable. | |
HEREDOC | |
puts human.instance_of?(Human) | |
puts human.instance_of?(MeowingBehavior) | |
puts human.kind_of?(MeowingBehavior) | |
puts <<HEREDOC | |
> A behavior could implement interfaces and inherit other behaviors, but | |
> it cannot inherit a class. | |
HEREDOC | |
# This will work ... | |
module ImplementsAndInherits | |
include BarkingBehavior | |
include MeowingBehavior | |
def implementation | |
puts "I can implement stuff." | |
puts "Also, I can bark like a dog." | |
3.times { bark } | |
end | |
end | |
include ImplementsAndInherits | |
implementation | |
puts "(See source code for example of syntax error)" | |
# module ImplementsAndInheritsAndSubclasses < ImplementsAndInherits | |
# include TalkingBehavior | |
# def implementation | |
# puts "This won't work." | |
# end | |
# end | |
puts <<HEREDOC | |
> A behavior could specify a constraint similar to a generic constraint where | |
> the class that implements a behavior must inherit a given base class. | |
HEREDOC | |
module TalkingBehavior | |
def self.included(includer) | |
if includer.superclass == Human | |
puts "TalkingBehavior added to: #{includer}" | |
else | |
puts "TalkingBehavior must be included only by Humans" | |
end | |
end | |
def talk | |
puts "Hello, world!" | |
end | |
end | |
class TalkativeNonHuman | |
include TalkingBehavior | |
end | |
class TalkativeHuman < Human | |
include TalkingBehavior | |
end | |
puts "Creating a TalkativeHuman ..." | |
talky = TalkativeHuman.new | |
talky.talk | |
puts <<HEREDOC | |
> All protected and public members of a behavior must be overridable. | |
HEREDOC | |
noisy = NoisyHuman.new | |
noisy.bark | |
noisy.meow | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment