Я определяю класс Box в ruby, который имеет 3 переменных экземпляра: @length, @width, @height и 2 переменные класса: @@ boxcounter и @@ totalvolume.
Хотя значение @@ boxcounter может быть обновлено внутри конструктора объекта (инициализатора), обновление значения @@ totalvolume становится менее тривиальным, поскольку нам приходится пересчитывать объем данного объекта каждый раз, когда мы меняем любое из переменные экземпляра (т.е. длина, ширина или высота).
Я придумал следующий код для обработки этого варианта использования:
class Box
@@boxcounter = 0
@@totalvolume = 0.0
def initialize(length, width, height)
@length = length
@width = width
@height = height
@@boxcounter += 1
@@totalvolume += volume
end
def volume
volume = @length * @width * @height
end
def report
puts "# of boxes: #{@@boxcounter}"
puts "Total volume: #{@@totalvolume}"
puts "Average volume per box: #{@@totalvolume / @@boxcounter}"
end
def my_print
p self
puts "Length: #{@length}"
puts "Width: #{@width}"
puts "Height: #{@height}"
puts
end
def length=(length)
@@totalvolume -= volume
@length = length
@@totalvolume += volume
end
def width=(width)
@@totalvolume -= volume
@width = width
@@totalvolume += volume
end
def height=(height)
@@totalvolume -= volume
@height = height
@@totalvolume += volume
end
end
Поскольку идея изучения объектов первого класса все еще остается в моей голове после изучения Scheme, я подумал: могу ли я создать универсальный установщик и использовать его для уменьшения повторения кода в каждом из перечисленных выше сеттеров? Я пробовал это, но использование eval, похоже, немного взломать:
def update_class_state(update_instance_variable)
@@totalvolume -= volume
eval update_instance_variable
@@totalvolume += volume
end
def length=(length)
update_class_state("@length = #{length}")
end
def width=(width)
update_class_state("@width = #{width}")
end
def height=(height)
update_class_state("@height = #{height}")
end
- Мой вопрос: это плохая практика - писать такой код? Есть ли более элегантное решение для этого подхода?