我想做一些检查作家访问器。我的第一个想法是返回一个布尔值。
class MyClass
def var=(var)
@var = var
# some checking
return true
end
end
m = MyClass.new
retval = (m.var = 'foo')
=> "foo"
我可以在写入器访问器中设置返回值吗?如果是,我怎样才能得到这个值?
我会使用 set_var(var) 而不是您尝试做的事情,假设属性编写器可以正常工作。您正在尝试做的事情对于下一个使用您的代码的穷人来说是非标准且不明显的。(可能只是你自己)如果发送了错误的输入或发生了相当异常的事情,我会抛出异常。
你想要这种行为
Correct
>>temp = object.var = 7
=> 7
Wrong
>>temp = object.var = 7
=> false
= 运算符应始终返回传递给它的值。Ruby 使用隐式返回,这在编程语言中并不常见。使用时仔细检查退货method=()
。
class Test
def var=(var)
@var = var
return true
end
end
t1, t2 = Test.new, Test.new
t1.var = 123 # evaluates to 123
# Why is it impossible to return something else:
t1.var = t2.var = 456
如评论中所述:我相信不可能更改返回值以允许链式分配。无论如何,大多数 Ruby 程序员可能都不会改变返回值。
免责声明:我测试了上面的代码,但没有发现明确的引用来验证我的陈述。
更新
class Test
def method_missing(method, *args)
if method == :var=
# check something
@var = args[0]
return true
else
super(method, *args)
end
end
def var
@var
end
end
t = Test.new
t.var = 123 # evaluates to 123
t.does_not_exists # NoMethodError
这似乎真的不可能!上面的示例表明返回值根本与var=
方法无关。你无法改变这种行为——这是 Ruby 赋值的基本方式。
更新 2:找到解决方案
你可以提出一个例外!
class Test
def var=(var)
raise ArgumentError if var < 100 # or some other condition
@var = var
end
def var
@var
end
end
t = Test.new
t.var = 123 # 123
t.var = 1 # ArgumentError raised
t.var # 123
此外,根据您的示例,要清理内容,您可以执行以下操作:
class MyClass
attr_accessor :var
end
m = MyClass.new
m.var = "Test"
puts m.var # => "Test"
不过,关于您的问题,您是否在问是否可以返回您为对象的值设置的值以外的值?
更新
看看这个项目:Validatable。它将类似于 ActiveRecord 的验证添加到您的类属性中。
快速场景:
class Person
include Validatable
validates_presence_of :name
attr_accessor :name
end
class PersonPresenter
include Validatable
include_validations_for :person
attr_accessor :person
def initialize(person)
@person = person
end
end
presenter = PersonPresenter.new(Person.new)
presenter.valid? #=> false
presenter.errors.on(:name) #=> "can't be blank"
我知道这是对派对的迟到回应...
很难知道你在课堂上试图做什么。您提到要在保存...到数据库之前对其进行检查?文件?
如果属性值不正确,您希望发生什么?
通过使用布尔返回,您可以有效地“隐藏”错误(因为您会忘记必须检查 setter 的返回值的奇怪事情)。
虽然你可以按照别人的建议去做
你也可以考虑一个isValid?像许多最终被持久化的类一样的方法。然后保存可以检查对象的状态并抛出错误。
底线:
帮助推动解决方案的一种方法是考虑首先编写您正在寻找的行为(即BDD)。然后,通过TDD进一步研究类应该做什么,使用RSpec获得所需的类“合同”,该合同需要出现以支持所需的行为。