Preface
Ruby 中,模組(Module)中可以定義變數與方法。透過適當的設計,你可以將物件之間可能共用的實作抽離至模組中,在必要時讓類別 include,使得類別定義時得以精簡。
定義模組
舉個例子來說,你會定義以下的球類別,並定義了一些比較大小的方法:
- class Ball
- attr_reader :radius
- def initialize(radius)
- @radius = radius
- end
- def <=>(that) self.radius - that.radius end
- def <(that) (self <=> that) < 0 end
- def <=(that) (self < that) || (self <=> that) == 0 end
- def >(that) !(self <= that) end
- def >=(that) !(this < that) end
- def ==(that) (self <=> that) == 0 end
- def eql?(that)
- if self.equal?(that)
- return true
- end
- if that.is_a?(Ball)
- return self == that
- end
- return false
- end
- def hash
- 41 * @radius
- end
- def to_s
- "Ball(#{@radius})"
- end
- end
- module Comparable
- def <=>(that)
- raise RuntimeError, "必須實作 <=> 方法"
- end
- def <(that) (self <=> that) < 0 end
- def <=(that) (self < that) || (self <=> that) == 0 end
- def >(that) !(self <= that) end
- def >=(that) !(this < that) end
- def ==(that) (self <=> that) == 0 end
- end
- class Ball
- include Comparable
- attr_reader :radius
- def initialize(radius)
- @radius = radius
- end
- def <=>(that) self.radius - that.radius end
- def eql?(that)
- if self.equal?(that)
- return true
- end
- if that.is_a?(Ball)
- return self == that
- end
- return false
- end
- def hash
- 41 * @radius
- end
- def to_s
- "Ball(#{@radius})"
- end
- end
類似地,如果你在收集物件之後,必須迭代、取得最大物件、最小物件、排序、尋找物件等動作,不用親自撰寫,只要 include 內建的 Enumerable 模組就可以了。例如:
- class Pond
- include Enumerable
- def initialize(list = [])
- @list = list
- end
- def <<(obj)
- @list << obj
- end
- def each
- @list.each { |obj|
- yield(obj)
- }
- end
- end
- pond = Pond.new([Ball.new(10), Ball.new(20)])
- pond << Ball.new(5)
- pond << Ball.new(15)
- pond << Ball.new(10)
- puts pond.include? Ball.new(5) # true
- print "#{pond.sort}\n" # [Ball(5), Ball(10), Ball(10), Ball(15), Ball(20)]
- puts "Max: #{pond.max}" # Max: Ball(20)
- puts "Min: #{pond.min}" # Min: Ball(20)
- pond.each_with_index do |ball, index|
- puts "#{index} - #{ball}"
- end
Supplement
* Ruby 手冊 - 模組 modules
* Ruby tutorialspoint - Modules & Mixin
沒有留言:
張貼留言