Ruby 中的实例变量的通用 setter?
Generic setter for instance variables in Ruby?
我在 ruby 中定义了一个 Box class,它有 3 个实例变量:@length、@width、@height 和 2 个 class 变量:@@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 后第一个 class 个对象的想法仍然在我脑海中,我想知道,我是否可以创建一个泛型 setter 并使用它来减少每个对象中的代码重复setters 上面列出了吗?我试过了,但是使用 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
– 我的问题:像这样编写代码是一种不好的做法吗?这种方法有更优雅的解决方案吗?
除了使用 eval 之外,您的方法本身 "wrong" 没有任何其他内容。
这是一种无需使用 eval
即可删除重复的更动态的方法
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 "Height: #{@height}"
end
# dynamically define your methods to dry up the code:
%w[length width height].each do |method|
define_method("#{method}=") do |arg|
@@totalvolume -= volume
instance_variable_set('@'+method, arg)
@@totalvolume += volume
end
end
end
我在 ruby 中定义了一个 Box class,它有 3 个实例变量:@length、@width、@height 和 2 个 class 变量:@@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 后第一个 class 个对象的想法仍然在我脑海中,我想知道,我是否可以创建一个泛型 setter 并使用它来减少每个对象中的代码重复setters 上面列出了吗?我试过了,但是使用 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
– 我的问题:像这样编写代码是一种不好的做法吗?这种方法有更优雅的解决方案吗?
除了使用 eval 之外,您的方法本身 "wrong" 没有任何其他内容。 这是一种无需使用 eval
即可删除重复的更动态的方法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 "Height: #{@height}"
end
# dynamically define your methods to dry up the code:
%w[length width height].each do |method|
define_method("#{method}=") do |arg|
@@totalvolume -= volume
instance_variable_set('@'+method, arg)
@@totalvolume += volume
end
end
end