如何避免实例变量初始化丑陋

How to avoid instance variable initializing ugliness

我经常在我的代码中看到它弹出

class Foo
  def initialize(foo)
    @foo = foo
  end
  #...
end

这还不错,但会变得更糟:

class Foo
  def initialize(foo,baz,bar,a,b,c,d)
    @foo = foo
    @baz = baz
    @bar = bar
    #etc...

你可以通过做类似

的事情来解决这个问题
@foo, @baz, @bar = foo, baz, bar

但即使那样感觉也不对,打字也很烦人。有没有更好的方法根据参数定义实例变量?

编辑: 这个问题似乎有两种不同的解决方案。参见:

def initialize args
  @foo, @baz, @bar = *args
end

您可能要考虑使用 Struct:

class Foo < Struct.new(foo,baz,bar,a,b,c,d)
end

foo = Foo.new(1,2,3,4,5,6,7)
foo.bar #=> 2

根本不需要定义额外的initialize方法...

是的,这是在 Ruby 中初始化实例变量的首选方式。打字可能很烦人,但这是一个很好理解的模式。与 Ruby 一样,使用元编程将其自动化是可能的,但会使您的代码更难理解。

我还认为,当 class 接受超过两个或三个参数时,看起来丑陋可能是一件好事。如果您的 class 依赖于六种不同的东西来发挥作用,那么它很适合进行重构。

我认为有3种方法可以缩短实例变量的初始化时间:

  1. 使用 Struct 或 OpenStruct。
  2. 使用ruby的并行赋值。
  3. 使用元编程制作类似this的宏。

fattr gem 最近在 Ruby Tapas 上得到认可,以帮助解决这个问题。不过,另一个考虑因素是是否有太多东西被传递到初始化程序中。可能是这个 class 做的太多了,需要分解成更小的部分。