【问题标题】:Get name of anonymous class while inherited process继承进程时获取匿名类的名称
【发布时间】:2014-06-04 06:26:16
【问题描述】:

是否有可能在继承的匿名类中获得name,而不是引发“失败A”?应通过Class 对象创建(无 eval 或类似)进行。

class A
  def self.inherited(base)
    raise 'fail A' unless base.name
  end
end

B = Class.new(A)
# or
Object.const_set :B, Class.new(A)

上面的代码不起作用,因为匿名类还没有初始化,所以不能设置为特定的常量。

【问题讨论】:

    标签: ruby class metaprogramming


    【解决方案1】:

    没有。

    一个匿名类在被分配给一个常量之前是没有名字的(例如(B = Class.new).name #=> "B")。由于在创建类实例之前不会进行分配(在此期间调用了包括 inherited 在内的钩子),因此在此之前您无法获得名称。

    【讨论】:

    • 是的,没错,但可能有一些 hack。我试图在块中定义def self.name; 'B'; end,因为我虽然它会首先定义名称类方法,然后会调用inherited,但没有。对我来说,这种行为真的很奇怪。
    • 这行不通,因为和上面一样,钩子是在方法定义的块被评估之前调用的,所以该方法还不存在。
    【解决方案2】:

    类似的东西呢:

    class Superclass
      def self.inherited(base)
        raise 'Invalid class name' unless @forced_anonymous_subclass_name == :A
      end
      def self.forced_anonymous_subclass_name
        @forced_anonymous_subclass_name
      end
      def self.with_forced_anonymous_subclass_name(class_name)
        @forced_anonymous_subclass_name = class_name
        yield
      ensure
        @forced_anonymous_subclass_name = nil
      end
    end
    
    sc = Superclass
    
    sc.with_forced_anonymous_subclass_name(:A) do
      Object.const_set sc.forced_anonymous_subclass_name, Class.new(sc)
    end #=> A
    
    sc.with_forced_anonymous_subclass_name(:B) do
      Object.const_set sc.forced_anonymous_subclass_name, Class.new(sc)
    end #=> RuntimeError
    

    如果不清楚/改进/等,请随时询问。

    【讨论】:

    • 您好@mdesantis,我真正想要解决的是这个问题:github.com/gregbell/active_admin/blob/master/lib/active_admin/… 您的解决方案将不起作用,因为它会在 ActiveSupport 代码中的某处检查name 方法。但我会检查以确保它不会工作......也许你知道一些更清洁的解决方案?
    • 哦...那行有什么问题?你说的是什么问题?如果您告诉我您要解决的问题,我们可以对此进行推理;你需要替换eval
    • 没错,我不知道怎么把eval换成更合适的,比如Module.new
    • 那么Object.const_set config.controller_name, Class.new(ActiveAdmin::PageController) 呢?考虑过吗?
    • 我不明白你所说的比eval“更合适”的东西是什么意思。在这种情况下,eval 似乎是足够的定义。也许你的意思是更优雅,但你在这里谈论的是一个边缘情况:基本上你想要一个原子的命名匿名类初始化操作。这不是通常需要的东西,我认为这是eval 的完美用例。如果它让您如此困扰,那么我认为最容易实现的目标是使可继承类与匿名类兼容,这可能比需要数年时间才能成为足以依赖的标准的新核心功能更合理。
    猜你喜欢
    • 2011-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多