这是Ruby中的一个很好的编程实践吗?

时间:2013-12-23 10:01:29

标签: ruby

class A
  attr_accessor :m

  def n
    @m + 1
  end
end

a = A.new
a.m = 4
p a.n

我在讨论“n”方法中你有@m + 1的代码。这种代码是否容易崩溃,因为我没有要求用户为@m变量赋值? / p>

3 个答案:

答案 0 :(得分:1)

作为一般规则,属性在适当时应具有默认值,或者值应传递到构造函数中。在上述情况下,如果您删除a.m = 4行并运行代码,则会出现此错误:

some.rb:5:in `n': undefined method `+' for nil:NilClass (NoMethodError)
from some.rb:10:in `<main>'

对于对象,如果属性具有默认值,则要求它们通过构造函数传入,如果不是,则失败。这确保了无论对象如何实例化,您都将拥有一个理智的默认值。绕过一个具有暴露值的物体,就像代码中的定时炸弹一样。

答案 1 :(得分:0)

您的代码有两点令人不安:

  1. 您应该使用attr_accessor的变量名引用值,而不是它们的实例变量名,这意味着这样做

    def n
      m + 1 # and not @m + 1
    end
    
  2. 如果一个变量可以是nil,你应该以某种方式防止涉及nil的所有操作,即使这意味着引发自定义错误,因为“未定义的方法+用于NilClass”是不是一个真正描述性的错误。这意味着写这样的东西会更好

    def n
      raise StandardError.new("m is not set in instance of A") if m.nil?
      m + 1
    end
    

    如果您要寻找错误,这将节省您的时间。此外,您可以使用m的默认值(如果有),而是将其设置为初始化:

    def initialize
      super()
      self.m = 3 #or
      # self.m ||= 3 This would only set m if it wasn't set by initialization in a superclass
    end
    

答案 2 :(得分:0)

当属性是可选的或不需要构建对象时,使用基于setter的依赖注入,当构建对象(或其关键功能)需要属性时,使用基于构造函数的依赖注入。

在你的情况下,如果你的类中唯一的对象是调用方法n,那么使用构造函数来提供m否则使用setter