【问题标题】:Shared class instance variable in one line of code一行代码中的共享类实例变量
【发布时间】:2020-04-16 10:36:09
【问题描述】:

我想要一个类似的系统:Widgets 的层次结构,每个 Widget 包含一个类实例变量 @painter。因此Widget 的每个实例都知道如何绘制自己,但这种行为可以在运行时替换。

目前我有这样的事情:

class MyButton < Widget

  @painter = DefaultPainter.new

  def set_painter(new_painter)
    self.class.instance_variable_set(:painter, new_painter)
  end

  def get_painter()
    self.class.instance_variable_get(:painter)
  end

end

是否有可能(可能使用元编程)将此冗长的代码缩减为:

class Widget

  shared_attr :painter

end

可能最好的方法是在 Widget.inherit 覆盖中使用 define_method。它可以为每个类设置方法和@painter。但我不确定这种方式是否最好。例如,如果我创建 Button &lt; WidgetSpecialButton &lt; Button,我希望 SpecialButton 获取 @painter 类实例变量。

另外,如果我想在其他课程中有shared_attrs 怎么办。也许我可以写一个HasSharedVariables 模块。每个需要共享变量的类都可以扩展这个模块。如果可能的话,我想知道最好的方法。

【问题讨论】:

  • “共享变量”的目的是什么?也许您想要的是全局变量或常量?你可能应该看看this question
  • 不好的术语,我的意思是类层次结构中类的每个实例都有一个变量。我可以使用@@variable,但这基本上就像变相的全局变量。我需要的是该类及其每个后代(直接或间接)的一个变量。
  • 您的想法仍然令人费解。变量意味着状态可以改变。你需要“变量”来改变什么?仅仅因为 Ruby 允许元编程,并不意味着您需要这样做。您要解决的问题到底是什么?你甚至尝试过白板吗?

标签: ruby


【解决方案1】:

如果您想在类之间共享代码,而这不能通过类继承轻松完成,那么您可能需要一个模块。

module Paint
  def paint 
    puts "hooray I paint #{self.foo if defined?(self.foo)}"
  end
end

class Widget
  include Paint

  attr_accessor :foo

  def initialize
    @foo = 'foo'
  end

  def scribble
    puts "I scribble some #{foo}" 
  end
end

w = Widget.new
w.paint
hooray I paint foo

w.scribble
I scribble some foo
w.foo='splat'
w.paint
hooray I paint splat

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-14
    • 1970-01-01
    • 1970-01-01
    • 2018-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多