【问题标题】:How to make Class.clone or Class.dup work in ruby?如何使 Class.clone 或 Class.dup 在 ruby​​ 中工作?
【发布时间】:2012-12-04 21:58:35
【问题描述】:

我有一个名为 Client 的模型,我想在某些情况下克隆它,其中客户端(现实世界的那种)进行了需要更改类级别的修改。

例如,如果我有:

class Client
  set_table_name :clients

  def some_method
    puts "Hello"
  end
end

如果我有以下情况:

module ClientA
  def some_method
    puts "World"
  end
end

我希望我可以克隆(或复制)该类,然后包含模块以覆盖方法 some_method

但这是在我的生产控制台中发生的事情:

> CA = Client.dup
> CA.singleton_class.send(:include, ClientA) # Or just CA.send(:include, ClientA)
> client = CA.new
> client.some_method
=> "Hello" # Expected "World"

这有什么诀窍吗?

【问题讨论】:

  • 不是一个真正的答案,但是“我的客户需要特定类别的更改”是什么意思?我知道 ruby​​ 很好而且很灵活,但是如果你每次你的客户改变他的心情并要求你“改变软件的行为,但只针对客户端 X”时动态地创建一个新类,你或多或少地要求麻烦...最终会得到一堆无法调试的垃圾软件。
  • 是的,我知道。我不是这个请求的粉丝,但我试图找到一些优雅的方式来做到这一点。到目前为止还没有真正发现任何东西(不确定我会不会)。

标签: ruby class clone


【解决方案1】:

使用 Class.new(Client) 代替 Client.dup,它是 Client 的子类。

如果您想避免这种情况,这似乎适用于Client.dup

CA.send(:define_method, :some_method) do 
  puts "World"
end

【讨论】:

  • 成功了!你能解释一下这背后的一些机制吗?
  • Class.new(parent) 声明父类的子类。我不确定 Class#dup 会在幕后做什么......
  • 我建议将该评论移到答案中以避免标记(由于正文非常小,缺乏解释等)。
  • 这里唯一的问题,没有指定是我的错,但我试图避免子类化。无论如何,我都会选择这个答案,因为它确实完成了工作——只是不是我希望的方式。谢谢。
【解决方案2】:

如果你想用模块的数据覆盖特定的类,你想扩展它。

client = Client.new
client.extend(ClientA)
client.some_method
=> "World"

你可以在这里看到它的工作原理:http://rubyfiddle.com/riddles/7621e

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 2015-08-05
    • 2015-11-12
    • 2014-12-15
    • 2011-06-27
    • 2011-02-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多