10

1 つのスーパークラスから継承する多数のクラスがあります。定義されたモジュールとしてのスーパークラス。モジュールの内部には、いくつかのインスタンス変数を設定する self.include(base) メソッドがあります。

だから、このようなもの:

module MyModule
  def self.included(base)
    base.instance_variable_set("@my_instance_variable", {})
  end
end

class MySuperClass
  include MyModule
end

class ClassA < MySuperClass
end

class ClassB < MySuperClass
end

MyModule を ClassA と ClassB に明示的に含めない限り、インスタンス変数はこれら 2 つのクラスに設定されません。

モジュールを明示的にインクルードしなくても、モジュールの self.included(base) メソッドが各サブクラスで実行されるようにする方法はありますか? すでにスーパークラスに含まれているためです。

4

1 に答える 1

16

クラス インスタンス変数は、クラスに対してプライベートです。継承されたクラスはそれらに直接アクセスできません。ここにはいくつかの方法があります。

1.アクセサを定義する

module MyModule
  def self.included(base)
    base.instance_variable_set :@my_instance_variable, {}
    base.extend ClassMethods
  end

  module ClassMethods
    def my_instance_variable
      # self is ClassA here, so we need to call superclass
      superclass.instance_variable_get :@my_instance_variable # => {}
    end
  end
end

class MySuperClass
  include MyModule
end

class ClassA < MySuperClass; end

ClassA.my_instance_variable # => {}

2. よりメタプログラム的

しかし、クラスが継承されるたびに呼び出されるフックがあります。この時点で変数を設定できます。これをチェックしてください。

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

  module ClassMethods
    # make it a class method. It will be called on target classes later.
    def enhance klass 
      klass.instance_variable_set("@my_instance_variable", {})
    end
  end
end

class MySuperClass
  include MyModule

  # this hook will get called on 'class ClassA < MySuperClass`
  def self.inherited klass
    # set class instance var on child class
    enhance klass
  end
end

class ClassA < MySuperClass; end

ClassA.instance_variable_get '@my_instance_variable' # => {}

注:このサンプルでは、​​継承された各クラスが独自のクラス インスタンス var を取得します (基本クラスは取得しません)。これはあなたのケースにより適しているかもしれませんが、そうでないかもしれません。

于 2012-04-04T12:16:07.200 に答える