4

我想做一些检查作家访问器。我的第一个想法是返回一个布尔值。

class MyClass
  def var=(var)
    @var = var
    # some checking
    return true
  end
end

m = MyClass.new
retval = (m.var = 'foo')

=> "foo"

我可以在写入器访问器中设置返回值吗?如果是,我怎样才能得到这个值?

4

4 回答 4

9

我会使用 set_var(var) 而不是您尝试做的事情,假设属性编写器可以正常工作。您正在尝试做的事情对于下一个使用您的代码的穷人来说是非标准且不明显的。(可能只是你自己)如果发送了错误的输入或发生了相当异常的事情,我会抛出异常。

你想要这种行为

Correct
>>temp = object.var = 7
=> 7 

Wrong
>>temp = object.var = 7
=> false

= 运算符应始终返回传递给它的值。Ruby 使用隐式返回,这在编程语言中并不常见。使用时仔细检查退货method=()

于 2008-10-13T14:11:39.590 回答
4
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
于 2008-10-13T14:41:04.850 回答
2

此外,根据您的示例,要清理内容,您可以执行以下操作:

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"
于 2008-10-13T14:17:14.353 回答
1

我知道这是对派对的迟到回应...

很难知道你在课堂上试图做什么。您提到要在保存...到数据库之前对其进行检查?文件?

如果属性值不正确,您希望发生什么?

通过使用布尔返回,您可以有效地“隐藏”错误(因为您忘记必须检查 setter 的返回值的奇怪事情)。

虽然你可以按照别人的建议去做

  • 使用验证器插件
  • 引发错误

你也可以考虑一个isValid?像许多最终被持久化的类一样的方法。然后保存可以检查对象的状态并抛出错误。

底线:

  • 不要做你发布的事情
  • 抛出错误(通过任何已发布的解决方案)

帮助推动解决方案的一种方法是考虑首先编写您正在寻找的行为(即BDD)。然后,通过TDD进一步研究类应该做什么,使用RSpec获得所需的类“合同”,该合同需要出现以支持所需的行为。

于 2010-12-16T02:45:16.550 回答