Ruby获取继承类

7

我正在创建我的第一个Rails插件。由于我对Ruby还比较陌生,因此我想知道是否可能获取继承类?

例如,我正在尝试创建一个插件,以在不使用迁移时进行单元测试和功能测试。我的目标是初始化名为“controller”的类变量,使其初始化为正在测试的控制器类型。

如果我有一个基类ControllerTest:

class ControllerTest < Test::Unit::TestCase
  attr_accessor :controller

  def initialize
    super
    @controller = "call function that will find the inheriting classes name and create an instance of that controller type."
  end
end

目前我遇到的问题是如何获取继承类的名称。这可行吗?如果不行,是否有其他方法可以实现?

提前感谢。

4个回答

10

非常简单:使用“inherited”回调函数。

从Class类的RDoc中得知: inherited(subclass):每当当前类的一个子类被创建时调用的回调函数。

示例:

   class Foo
      def self.inherited(subclass)
         puts "New subclass: #{subclass}"
      end
   end

   class Bar < Foo
   end

   class Baz < Bar
   end
produces:

   New subclass: Bar
   New subclass: Baz

http://ruby-doc.org/core/classes/Class.html#M002785


1
由于问题提出者接受了我的回答,因此你给“没有回答问题”下的票似乎有些不正确。@fig-gnuton - Arkku
哈哈,你的选择仍然不够好。楼主显然不知道如何选择最佳答案。 :) - user65663
1
@fig-gnuton:OP选择了唯一符合他在问题中发布的代码示例的答案。您(以及其他许多帖子)解释末尾(无可否认地含糊不清)的措辞并不会改变OP所“想要”问的问题。因此,即使您的答案对于您认为的问题是完全有效的,这意味着该问题可能并不是非常清晰,但它得到了一个可以接受的答案。 - Arkku
1
(当然,您可以为OP的代码提出不同的设计,并修改您的答案以说明如何替换它,但现在它并没有导致“@controller被初始化为正在测试的控制器类型”。展示如何使用它更有建设性,而不是对问题和每个不同的解释进行投票...) - Arkku
我不同意。鉴于帖子标题和问题本身(包括代码示例)的措辞,你的选择仍然很差。 - user65663
我完全同意标题不明确,因为它没有指定获取继承类的上下文;它可能意味着在继承时(根据您的答案)。然而,代码示例显示OP想要在initialize方法中获取类的名称,以便创建另一个类的实例并将其分配给@controller。如果您认为您的答案适用于此示例,我会真诚地希望看到您如何在该上下文中使用它。 - Arkku

9

如果您想获取当前类的名称,可以使用self.class.name。如果您想获取超类,可以使用数组self.class.ancestors,例如self.class.ancestors[1].name。即时超类也可以使用self.superclass获得。

编辑,添加示例:

class ControllerTest
  attr_accessor :controller
  def initialize
    super
    @controller = eval "#{self.class.name}Controller.new(self)"
  end
end

class Foo <ControllerTest
end
class Bar <ControllerTest
end

class Controller
  def initialize (o)
    puts "Created #{self.class} to control #{o.class.name}"
  end
end

class FooController <Controller
end
class BarController <Controller
end

foo = Foo.new
bar = Bar.new

这个输出

Created FooController to control Foo
Created BarController to control Bar

2
未来参考,请使用“inherited”回调函数,这是最简单的方法。 - user65663
1
@fig-gnuton:如果是这样,请发布使用它完成相同事情的示例(=根据继承类的名称获取特定类型的控制器);对于日后发现此问题并确实打算询问如何使用“inherited”回调而不是本问题的人,这将非常有帮助。 - Arkku
1
能否解释一下为什么要给我点踩呢?虽然对于这个问题的解释存在分歧,但是这个答案中的代码确实可行并且回答了提问者的意图。如果它没有回答其他问题,那也不是答案的错。 - Arkku

1

我相信你需要在类被定义时捕获它们...

来自Class类的RDoc:

inherited(subclass)
Callback invoked whenever a subclass of the current class is created.

Example:

   class Foo
      def self.inherited(subclass)
         puts "New subclass: #{subclass}"
      end
   end

   class Bar < Foo
   end

   class Baz < Bar
   end
produces:

   New subclass: Bar
   New subclass: Baz

之前已经发布了相同的答案。 - user65663
当我开始发表这个答案时,你的答案还没有出现。很抱歉如果让你不开心,但在我发表我的答案之前我并没有看到你的答案。 - Mike Cargal

0

这将仅列出当前类中的实例方法

self.class.new.methods - self.class.ancestors[1].new.methods

通用解决方案如下:

c = some_class

c.new.methods - c.ancestors[1].new.methods


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接