2009-11-30 2 views
3

Я работаю на Chart класса и имеет параметр margin, который содержит :top, :bottom, :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, и я еще не привык ко всем идиомам. Итак, как вы думаете, ребята? Какой из лучших вариантов?

+0

Я не понимаю вашу озабоченность «пользователь может подумать, что поля содержат только: слева и справа». Как это отличается, когда вы используете синтаксис chart.marings (: left, 10)? – phtrivier

+0

Приятно, я пойду с решением парадигмы, добавив сахар Дуглы для маркерного сеттера в простых случаях. Спасибо вам всем! –

ответ

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 
+0

Не знаю. Возможно, создание класса для полей несколько завышено. Я бы предпочел, чтобы эти значения были хешированы. –

+1

Я не думаю, что здесь полезно использовать хэш, потому что есть только 4 возможных варианта. Поэтому, если вы пишете что-то вроде «: up => 10» вместо «: top => 10», вы будете испытывать ошибки, которые трудно обнаружить или добавить переключатель в вашу функцию, чтобы проверить все хеш-ключи ... – paradigmatic

2

В дополнении к ответу парадигматическому, вы могли бы добавить метод к классу Поля для поддержки:

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

Вы можете расширить метод marginins для обработки числового аргумента:

chart.margins = 20 

как su гар для:

chart.margins = Margins.new(20, 20, 20, 20) 
+0

Конечно. Я подумал об этом: «charts.margins (: all, 20)». –

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 
+0

Немного поместив, я думаю, что что-то вроде 'c.margins = {: top => 12,: bottom => 13}' является уродливым и может привести к путанице. И в конце концов, я не помню, чтобы увидеть что-нибудь подобное на любом Ruby-коде, с которым я работал. –

+0

Существует также синтаксис, который позволит вам написать c.set_margins (: top => 12,: bottom => 13) - то есть вы передаете хэш функции, но поскольку это единственный аргумент, вы не нужно писать фигурные скобки. Будет ли это выглядеть лучше для вас? – phtrivier

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 

Но я думаю, я бы выбрал подход парадигматическую в любом случае ...

1

Вы также можете придерживаться с тем, что вам был первым и использовал обычный хэш-синтаксис.

margins["left"] = 10 #to set just one without changing the others 
Смежные вопросы