如何在Ruby中动态改变继承

Gra*_*ean 11 ruby metaprogramming

我想在Ruby中动态指定类的父类.考虑以下代码:

class Agent
  def self.hook_up(calling_class, desired_parent_class)
    # Do some magic here
  end
end

class Parent
  def bar
    puts "bar"
  end
end

class Child
  def foo
    puts "foo"
  end

  Agent.hook_up(self, Parent)
end

Child.new.bar
Run Code Online (Sandbox Code Playgroud)

类和定义都Parent没有Child指定父类,所以它们都从Object继承.我的第一个问题是:Agent.hook_up为了制作Parent超类,我需要做些什么Child(例如Child对象可以继承'bar'方法).

我的第二个问题是:我是否需要传递第一个参数Agent.hook_up,或者是否有某种hook_up方法可以通过编程方式确定调用它的类?

Jos*_*eek 23

也许你正在寻找这个

Child = Class.new Parent do
  def foo
    "foo"
  end
end

Child.ancestors   # => [Child, Parent, Object, Kernel]
Child.new.bar     # => "bar"
Child.new.foo     # => "foo"
Run Code Online (Sandbox Code Playgroud)

由于parent是Class.new的参数,因此可以将其与其他类交换.

在编写某些类型的测试之前,我已经使用过这种技术.但我很难找到许多有利于做这件事的好借口.


我怀疑你真正想要的是一个模块.

class Agent
  def self.hook_up(calling_class, desired_parent_class)
    calling_class.send :include , desired_parent_class
  end
end

module Parent
  def bar
    "bar"
  end
end

class Child
  def foo
    "foo"
  end

  Agent.hook_up(self, Parent)
end

Child.ancestors   # => [Child, Parent, Object, Kernel]
Child.new.bar     # => "bar"
Child.new.foo     # => "foo"
Run Code Online (Sandbox Code Playgroud)

当然,虽然根本不需要代理

module Parent
  def bar
    "bar"
  end
end

class Child
  def foo
    "foo"
  end

  include Parent
end

Child.ancestors   # => [Child, Parent, Object, Kernel]
Child.new.bar     # => "bar"
Child.new.foo     # => "foo"
Run Code Online (Sandbox Code Playgroud)


sep*_*p2k 6

Joshua已经为您提供了很多替代方案,但是要回答您的问题:在ruby中创建类之后,您无法更改类的超类.这根本不可能.

  • 接受挑战! (8认同)
  • @Borromakot的挑战状态? (3认同)