# CSE341 - mixins # mixins provide a convenient way to define some functionality -- # outside of a class -- that can be 'mixed in' to any class. Ruby # only has single inheritance (at most one superclass per class), but # you can mix in as many mixins as you want. # let's define a mixin called Doubler module Doubler def double self + self # uses self's + message, not defined in Doubler end end class String include Doubler end # now try "octopus ".double # mix it into another class class Array include Doubler end # we could also add it to all numeric classes (integers, floats etc): # class Numeric # include Doubler # end # The Comparable and Enumerable mixins are probably the most commonly # used ones in the Ruby library # For Comparable you define <=>, # and you get ==, >, <, >=, <= from the mixin # (overrides Object's ==, adds the others) class Name attr_accessor :first, :middle, :last include Comparable def initialize(first,last,middle="") @first = first @last = last @middle = middle end def <=> other # compare the last names, using <=> defined on strings compare_last = @last <=> other.last # if they are unequal we are done - return that result return compare_last if compare_last != 0 # last names were the same - go on to check the first names compare_first = @first <=> other.first return compare_first if compare_first != 0 # first names were also the same - check the middle name @middle <=> other.middle end end # For Enumerable you define each, and you get map, any?, etc. If the # objects in the collection implement a meaningful <=> operator, you also # get max, min, and sort. Note that map always returns an array, rather # than the same kind of object to which you send the map message. # Example of using Enumerable - a range class. Let's call the class # MyRange to avoid messing up the builtin class Range. If you give MyRange # numbers for low and high, since they implement <=> MyRange will provide # max, min, etc. class MyRange include Enumerable def initialize(low,high) @low = low @high = high end def each i=@low while i <= @high yield i i=i+1 end end end # here is how module Enumerable could implement map: # def map # arr = [] # each {|x| arr.push (yield x) } # arr # end