Вопрос
Я работаю над классом Chart
, и у него есть параметр margin
, который содержит : top
, : bottom < Значения / code>,
: right
и : left
. Моим первым вариантом было сделать margin
установщиком и установить значения следующим образом:
# Sets :left and :right margins and doesn't alter :top and :bottom
chart.margins = {:left => 10, :right => 15}
Это хорошо, потому что это явно сеттер, но, подумав, я думаю, это тоже может сбить с толку: пользователь может подумать, что поля содержат только : left
и : right
значения, что не правильно. Другой вариант - устранить =
и сделать его обычным методом:
chart.margins(:left => 10, :right => 15)
С помощью этого синтаксиса легко понять, что происходит, но он не является стандартным установщиком и конфликтует с геттером margins
. И есть еще один вариант:
chart.margins(:left, 10)
chart.margins(:right, 15)
Я не знаю, что об этом думать. Для меня очевидно, что метод является установщиком, но на этот раз я не могу установить несколько значений одним вызовом, и снова возникает проблема с геттером. Я относительно новичок в Ruby и еще не привык ко всем идиомам. Итак, что вы думаете, ребята? Какой самый лучший вариант?
Решение
Вы также можете создать класс Margin, который будет иметь следующий четкий синтаксис:
class Margin
attr_accessor :left, :right, :top, :bottom
...
end
class Chart
attr_accessor :margins
...
end
chart.margins.left = 10
puts chart.margins.right
Другие советы
Не уверен, что это тот синтаксис, который вы хотели бы сделать доступным (извините, если нет:)
#!/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
В дополнение к ответу парадигмы, вы можете добавить метод в класс Margins для поддержки:
chart.margins.set :left => 10, :right => 15
Вы можете расширить метод margins = для обработки числового аргумента:
chart.margins = 20
как сахар для:
chart.margins = Margins.new(20, 20, 20, 20)
Я не думаю, что создание класса для Margin является излишним. Вы всегда можете представить его значения в виде хэша, используя to_hash
или что-то подобное.
Кроме того, если хотите, вы можете заставить его работать в стиле DSL:
chart.margins do |m|
m.left 10
m.right 20
m.vertical 5 # sets both top and bottom margin
end
Но я думаю, что в любом случае я бы выбрал подход парадигмы ...
Вы также можете придерживаться того, что у вас было раньше, и использовать обычный синтаксис хеша.
margins["left"] = 10 #to set just one without changing the others