7

通常のメソッドルックアップパス、つまりを理解していますclass, superclass/module, all the way up to BasicObject。シングルトンバージョンのチェーンにも当てはまると思いましたが、メタチェーンにモジュールをミックスインした場合はそうではないようです。このモジュールをVehicleの固有クラスに含めたときに、次の例でシングルトンバージョンの代わりにAutomobileモジュールのメソッドが呼び出される理由を誰かが説明していただければ幸いです。banner

module Automobile
  def banner
    "I am a regular method of Automobile"
  end

  class << self
    def banner
      "I am a class method of Automobile"
    end
  end
end

class Vehicle 
  def banner
    "I am an instance method of Vehicle"
  end

  class << self
    include Automobile
    def banner
      puts "I am a class method of Vehicle"
      super
    end
  end
end

class Car < Vehicle
  def banner
    "I am an instance method of Car"
  end

  class << self
    def banner
      puts "I am a class method of Car"
      super
    end
  end
end

puts Car.banner

# I am a class method of Car
# I am a class method of Vehicle
# I am a regular method of Automobile
4

2 に答える 2

8

まず第一に、includeあなたが期待するかもしれないように固有クラスのメソッドを含みません。検討:

module Foo
  class << self
    def do_something
      puts "Foo's eigenclass method does something"
    end
  end
end

module Bar
  include Foo
end

puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)

これは、古典的に定義されたクラスメソッドの動作と一致していることに注意してください。

module Foo
  def self.do_something
    puts "Foo's class method does something"
  end
end

module Bar
  include Foo
end

puts Bar.do_something
# undefined method `do_something' for Bar:Module (NoMethodError)

extend一般的なイディオムは、サブモジュールでクラスメソッドを定義し、モジュールが含まれているときにへの呼び出しをトリガーすることです。

module Foo
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def do_something
      puts "Foo::ClassMethod's instance method does something"
    end
  end
end

module Bar
  include Foo
end

puts Bar.do_something
# Foo::ClassMethod's instance method does something

2つ目の注意点は、のインスタンスメソッドをの固有クラスに実際に含めていることですAutomobileVehicleしたがって、のインスタンスメソッドは。Automobileの(固有)クラスメソッドになりVehicleます。

あなたのCarクラスは基本的にこれらすべてとは何の関係もありません。ここで注意すべき唯一のことは、クラスの継承によってクラスメソッドも使用できるようになるのに対し、使用できincludeないということです。例:

class Foo
  def self.do_something
    puts "Foo's class method does something"
  end
end

class Bar < Foo
end

puts Bar.do_something
# "Foo's class method does something"
于 2012-11-07T13:15:40.817 に答える
2

まず第一に、クラスはオブジェクトであり、他のオブジェクトと同様に独自のスーパークラスも持っています。第二に、Eigenclass 自体は通常のクラスであり、匿名であり、目に見えないだけです。3 番目に、派生クラスの固有クラスのスーパークラスは基本クラスの固有クラスです。4つ目includeは、インクルードされたモジュールのインスタンス メソッド (シングルトン メソッドではない) をインクルードし、それらをレシーバー クラス オブジェクトのインスタンス メソッドにします。

あなたの例には2つの並列継承チェーンがあります

車 < 乗り物 < ...

車の固有種 < 車の固有種 < 自動車 < ...

irb で次のテストを実行します。

class Object
  def eigenclass
    class << self
      self
    end
  end
end

Car.ancestors # => [Car, Vehicle, Object, Kernel, BasicObject]
Car.eigenclass.ancestors # => [Automobile, Class, Module, Object, Kernel, BasicObject]
Vehicle.eigenclass.ancestors # => [Automobile, Class, Module, Object, Kernel, BasicObject]
Car.eigenclass.superclass.equal? Vehicle.eigenclass # => true

ほら、Automobile固有クラスの継承チェーンにあります。しかしancestor残念なことに、このメソッドは不可視の固有クラスを返しませんが、それらは実際には 2 番目のチェーンにあります。

于 2012-11-07T14:18:16.187 に答える