3

我正在研究一个Chart类,它有一个参数,margin它包含:top:bottom和值。我的第一个选择是制作一个设置器并设置如下值::right:leftmargin

# Sets :left and :right margins and doesn't alter :top and :bottom 
chart.margins = {:left => 10, :right => 15}

很好,因为它显然是一个 setter,但经过一番思考,我认为它也可能令人困惑:用户可能认为边距仅包含:left:right值,这是不对的。另一种选择是消除=并使其成为普通方法:

chart.margins(:left => 10, :right => 15)

使用这种语法,很容易弄清楚发生了什么,但它不是标准的 setter 并且与marginsgetter 冲突。还有另一种选择:

chart.margins(:left, 10)
chart.margins(:right, 15)

我不知道该怎么想。对我来说,很明显该方法是一个 setter,但是这次我不能通过一次调用来设置多个值,并且 getter 又出现了问题。我对 Ruby 比较陌生,还没有习惯所有的习语。那么,小伙伴们怎么看呢?哪个是最好的选择?

4

5 回答 5

5

您还可以创建一个 Margin 类来享受以下清晰的语法:

class Margin
    attr_accessor :left, :right, :top, :bottom
    ...
end

class Chart
    attr_accessor :margins
    ...
 end


chart.margins.left = 10
puts chart.margins.right
于 2009-11-30T12:36:18.380 回答
3

不太确定这是否是您想要提供的那种语法(对不起,如果不是:)

#!/usr/bin/ruby
class Margins < Struct.new(:top, :bottom, :left, :right) 
end

class Chart
  attr_reader :margins

  def initialize()
    @margins = Margins.new(0,0,0,0)
  end

  def margins=(hash)
    [:top, :bottom, :left, :right].each do |dir|
      if (hash[dir])
        @margins[dir] = hash[dir]
      end
    end
  end
end

c = Chart.new
c.margins.left = 10
c.margins={:top=>12,:bottom=>13}
puts c.margins.left
# 10
puts c.inspect;
# #<Chart:0xb7caaf8c @margins=#<struct Margins top=12, bottom=13, left=10, right=0>>

# However c.margins.foo = 12 would give you an error
于 2009-11-30T13:35:58.770 回答
2

除了范例的答案之外,您还可以向 Margins 类添加一个方法来支持:

chart.margins.set :left => 10, :right => 15

您可以扩展 margins= 方法来处理数字参数:

chart.margins = 20

作为糖:

chart.margins = Margins.new(20, 20, 20, 20)
于 2009-11-30T12:52:22.993 回答
2

我不认为为 Margin 创建一个类是矫枉过正的。您始终可以使用to_hash或类似的方式将其值公开为哈希值。

此外,如果你愿意,你可以让它以 DSL 风格工作:

chart.margins do |m|
  m.left 10
  m.right 20
  m.vertical 5 # sets both top and bottom margin
end

但我想我还是会选择范式的方法......

于 2009-11-30T16:34:11.953 回答
1

你也可以坚持你首先拥有的东西并使用普通的哈希语法。

margins["left"] = 10  #to set just one without changing the others
于 2009-11-30T17:10:39.413 回答