Ruby:如何为 class 字段的 << 方法添加验证
Ruby: How to add validation for a class field's << method
我了解如何实现(验证)setter (def item=
),但如何拦截字段上的 <<
操作?
class Bla
attr_reader :item
def initialize
@item = []
end
# only called for =, +=, -= operations (not <<)
def item=(value)
puts "Changing value to #{value}"
# pretend that there is a conditional here
@item = value
end
# This is wrong:
#def item<<(value)
# puts "adding value #{value}"
# @item << value
#end
end
b = Bla.new
b.item = ['one'] # works
b.item += ['one'] # works
b.item << 'two' # bypasses my setter
我试过了def item<<(value)
,好像不行。
class Pit
def <<(dirt)
puts 'shovel ' + dirt
end
end
Pit.new << 'sandy loam'
# => shovel sandy loam
当您调用 b.item << 'two'
时,您是在直接调用 item
上的 <<
方法。所以你在这里有几个选择:
直接在您的 Bla
class 上实施 <<
,然后使用 b << 'two'
:
# in class Bla
def <<(value)
# do validation here
@item << value
end
使用其他一些更好命名的包装器方法名称,例如 add_item
:
# in class Bla
def add_item(value)
# do validation here
@item << value
end
为 @item
使用一个特殊的数组 class,它有一个自定义定义 <<
:
class MyArray < Array
def <<(item)
# run validation here
super
end
end
# in Bla class
def initialize
@item = MyArray.new
end
我可能会选择选项 2,它最简单易读。
这是另一个建议:
class Bla
# DO NOT DEFINE A READER:
# attr_reader :item
def initialize
@items = []
end
def set_items(new_items)
puts "Changing value to #{new_items}"
# pretend that there is a conditional here
@items = new_items
end
def remove_item(item)
# pretend that there is a conditional here
@items -= items
end
def add_item(item)
# pretend that there is a conditional here
@items += items
end
end
通过不直接公开 @items
对象,您可以完全控制如何操作变量的接口。
(除非来电者做了一些非常骇人听闻的事情,比如 bla.instance_variable_get('@items')
!!)
我了解如何实现(验证)setter (def item=
),但如何拦截字段上的 <<
操作?
class Bla
attr_reader :item
def initialize
@item = []
end
# only called for =, +=, -= operations (not <<)
def item=(value)
puts "Changing value to #{value}"
# pretend that there is a conditional here
@item = value
end
# This is wrong:
#def item<<(value)
# puts "adding value #{value}"
# @item << value
#end
end
b = Bla.new
b.item = ['one'] # works
b.item += ['one'] # works
b.item << 'two' # bypasses my setter
我试过了def item<<(value)
,好像不行。
class Pit
def <<(dirt)
puts 'shovel ' + dirt
end
end
Pit.new << 'sandy loam'
# => shovel sandy loam
当您调用 b.item << 'two'
时,您是在直接调用 item
上的 <<
方法。所以你在这里有几个选择:
直接在您的
Bla
class 上实施<<
,然后使用b << 'two'
:# in class Bla def <<(value) # do validation here @item << value end
使用其他一些更好命名的包装器方法名称,例如
add_item
:# in class Bla def add_item(value) # do validation here @item << value end
为
@item
使用一个特殊的数组 class,它有一个自定义定义<<
:class MyArray < Array def <<(item) # run validation here super end end # in Bla class def initialize @item = MyArray.new end
我可能会选择选项 2,它最简单易读。
这是另一个建议:
class Bla
# DO NOT DEFINE A READER:
# attr_reader :item
def initialize
@items = []
end
def set_items(new_items)
puts "Changing value to #{new_items}"
# pretend that there is a conditional here
@items = new_items
end
def remove_item(item)
# pretend that there is a conditional here
@items -= items
end
def add_item(item)
# pretend that there is a conditional here
@items += items
end
end
通过不直接公开 @items
对象,您可以完全控制如何操作变量的接口。
(除非来电者做了一些非常骇人听闻的事情,比如 bla.instance_variable_get('@items')
!!)