Ruby/Language Basics/Modules Creation

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск

Содержание

Abstract method in a module

module Complaint
  def gripe
    voice("A")
  end
  def faint_praise
    voice("B")
  end
  def voice(complaint_text)
    raise NotImplementedError,
    "#{self.class} included the Complaint module but didn"t define voice!"
  end
end
class MyComplaint
  include Complaint
end
MyComplaint.new.gripe
# NotImplementedError: MyComplaint included the Complaint module
# but didn"t define voice!



access methods inside classes inside modules with Ruby scope resolution operator (::)

module Mathematics
  class Adder
    def Adder.add(operand_one, operand_two)
      return operand_one + operand_two
    end
  end
end
puts "2 + 3 = " + Mathematics::Adder.add(2, 3).to_s



Avoiding Naming Collisions with Namespaces

module StringTheory
  class String
    def initialize(length=10**-33)
      @length = length
    end
  end
end
String.new                                       # => ""
StringTheory::String.new
module StringTheory2
 RubyString = String
 class String
   def initialize(length=10**-33)
     @length = length
   end
  end
  RubyString.new("This is a built-in string, not a StringTheory2::String")
end
# => "This is a built-in string, not a StringTheory2::String"



Creating Modules

# To create a module, you use the module keyword. 
# You can place modules and the code that uses them in the same file, or break them out among separate files.
#file: mathematics.rb.
module Mathematics
  def Mathematics.add(operand_one, operand_two)
    return operand_one + operand_two
  end
end
file: sentence.rb
module Sentence
  def Sentence.add(word_one, word_two)
    return word_one + "" + word_two
  end
end
file: ModuleTest.rb
require "mathematics"
require "sentence"
puts "2 + 3 = " + Mathematics.add(2, 3).to_s



how to create a module and then include it in a class.

File: mixin.rb
#!/usr/bin/env ruby
module Dice
  # virtual roll of a pair of dice
  def roll
    r_1 = rand(6); r_2 = rand(6)
    r1 = r_1>0?r_1:1; r2 = r_2>0?r_2:6
    total = r1+r2
    printf( "You rolled %d and %d (%d).\n", r1, r2, total )
    total
  end
end
class Game
 include Dice
end
g = Game.new
g.roll



Initializing Instance Variables Defined by a Module

module Timeable
 attr_reader :time_created
  def initialize
    @time_created = Time.now
  end
  def age      #in seconds
    Time.now - @time_created
  end
end
class Character
  include Timeable
  attr_reader :name
  def initialize( name )
    @name = name
    super() #calls Timeable"s initialize
  end
end
c = Character.new "Fred"
c.time_created
# => Mon Mar 27 18:34:31 EST 2006
p Character.ancestors               #  => [Character, Timeable, Object, Kernel]



Involve demonstrating two classes with the same name, but in different modules

module ToolBox
  class Ruler
    attr_accessor :length
  end
end
module Country
  class Ruler
    attr_accessor :name
  end
end
a = ToolBox::Ruler.new
a.length = 50
b = Country::Ruler.new
b.name = "Ghengis Khan from Moskau"



Modules and Namespaces

Class.superclass                                  # => Module
puts Math.class                                        # => Module
puts Math.new



Modules provide a structure to collect Ruby classes, methods, and constants into a single, separately named and defined unit.

# Modules solve conflicts by providing namespaces that can contain any number of classes, 
# methods, and constants, and allow you to address them directly.:
module NumberStuff
  def NumberStuff.random
    rand(1000000)
  end
end
module LetterStuff
  def LetterStuff.random
    (rand(26) + 65).chr
  end
end
puts NumberStuff.random
puts LetterStuff.random



prefixed with the module name you can call the method from anywhere, as is the case with the Math module.

#!/usr/bin/env ruby
module Binary
  def Binary.to_bin( num )
    bin = sprintf("%08b", num)
  end
end
Binary.to_bin( 123 ) # => "01111011"



Print all classes (excluding exceptions)

puts Module.constants.sort.select {|x|
  c = eval(x.to_s)
  c.is_a? Class and not c.ancestors.include? Exception
}



Print all exceptions

puts Module.constants.sort.select {|x|
  c = eval(x.to_s)
  c.instance_of? Class and c.ancestors.include? Exception
}



Print all modules (excluding classes)

puts Module.constants.sort.select {|x| eval(x.to_s).instance_of? Module}



require the file containing the module, and then it would work (again, require is expecting a name in the load path).

module Dice
  # virtual roll of a pair of dice
  def roll
    r_1 = rand(6); r_2 = rand(6)
    r1 = r_1>0?r_1:1; r2 = r_2>0?r_2:6
    total = r1+r2
    printf( "You rolled %d and %d (%d).\n", r1, r2, total )
    total
  end
end
File: game.rb
#!/usr/bin/env ruby
require "dice"
class Game
 include Dice
end
g = Game.new
g.roll



store classes inside modules.

module Mathematics
  class Adder
    def Adder.add(operand_one, operand_two)
      return operand_one + operand_two
    end
  end
end



Use remove_const to delete a constant definition

# This should make things a lot simpler.
module Math
 remove_const(:PI)
  PI = 3
end
Math::PI                                        # => 3