Ruby/Language Basics/Mixins

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

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

Содержание

Automatically Initializing Mixed-In Modules

class Class
  def included_modules
    @included_modules ||= []
  end
  alias_method :old_new, :new
  def new(*args, &block)
    obj = old_new(*args, &block)
    self.included_modules.each do |mod|
      mod.initialize if mod.respond_to?(:initialize)
    end
    obj
  end
end
module Initializable
  def self.included(mod)
    mod.extend ClassMethods
  end
  module ClassMethods
    def included(mod)
      if mod.class != Module  #in case Initializeable is mixed-into a class
        puts "Adding #{self} to #{mod}"s included_modules" if $DEBUG
        mod.included_modules << self
      end
    end
  end
end
module A
  include Initializable
  def self.initialize
    puts "A"s initialized."
  end
end
module B
  include Initializable
  def self.initialize
    puts "B"s initialized."
  end
end
class BothAAndB
  include A
  include B
end
both = BothAAndB.new
# A"s initialized.
# B"s initialized.



Creating Mixins

# Creating a mixin using a module includes the code in a module inside a class and 
# gives you a way of inheriting from multiple modules.
module Adder
  def add(operand_one, operand_two)
    return operand_one + operand_two
  end
end
module Subtracter
  def subtract(operand_one, operand_two)
    return operand_one - operand_two
  end
end
class Calculator
  include Adder
  include Subtracter
end
calculator = Calculator.new()
puts "2 + 3 = " + calculator.add(2, 3).to_s



Mixing in Class Methods.rb

module MyLib
  module ClassMethods
    def class_method
      puts "in MyLib::ClassMethods"
    end
  end
end
module MyLib
  def self.included(receiver)
    puts "MyLib is being included in #{receiver}!"
    receiver.extend(ClassMethods)
  end
end
class MyClass
  include MyLib
end
# MyLib is being included in MyClass!
MyClass.class_method
# This method was first defined in MyLib::ClassMethods



Simulating Multiple Inheritance with Mixins.rb

require "set" 
module Taggable
  attr_accessor :tags
  def taggable_setup
    @tags = Set.new
  end
  def add_tag(tag)
    @tags << tag
  end
  def remove_tag(tag)
    @tags.delete(tag)
  end
end
module Taggable2
  def initialize(a,b,c)
  end
end
class TaggableString < String
  include Taggable
  def initialize(*args)
    super
    taggable_setup
  end
end
s = TaggableString.new("this is a test.")
s.add_tag "A"
s.add_tag "B"
s.tags



The Making of a Man

class Person
  attr_accessor :name, :age, :gender
end
person_instance = Person.new
person_instance.name = "Robert"
person_instance.age = 52
person_instance.gender = "male"
puts person_instance.name