在 Ruby 中,为什么有时候在实例变量前要使用下划线前缀?

4
我在Ruby类中看到一些人使用_前缀来定义实例变量,例如@_property,而在正常情况下,attr_writer使用普通名称,如@property来定义实例变量。这样做的意义和区别是什么?
2个回答

4

这里有2种可能的答案,取决于变量类型。

实例变量

当在实例变量前使用_(就像在你的问题中一样),这通常只是一种约定,以便清楚地表明该实例变量是私有实现细节,不应在当前范围之外使用。您可能会在要包含在其他类中的模块中遇到它,在这种情况下,实例变量由该模块定义和使用,但它属于对象本身并具有其作用域。我个人更喜欢基于对象的注册表,但"私有"实例变量是一种快速、简便且流行的方式。此外,将实例变量名称前缀为_可以降低名称冲突的机会。

# Library code
module SomeExternalLibraryModule
  def foo
    @_something ||= SomeExternalLibraryModule::Something.new(self)
  end
end

# Application code
class User
  include SomeExternalLibraryModule

  attr_reader :something # name conflict "avoided"! Phew!

  def bar
    @_something.do_sth 
    # "_" means - you'd better know what you're doing here!
    # There is no guarantee that instance variable will be present in the future release
  end
end

局部变量

当局部变量以下划线_为前缀时,表示该变量在代码中未被使用。这在使用迭代器或处理其他多元素输入时非常有用,特别是当您只对其中一个感兴趣时。

通常可以看到只有_作为变量名。对于解析器来说,它具有一些特殊含义,即您明确地表示“我不关心那是什么”。因此,在单个定义中允许多次使用它作为参数名称。

def foo(_, _, a)
  a
end

foo(1,2,3) #=> 3

def bar(a,a,b); end #=> SyntaxError

然而,通常最佳实践是在名称后使用“我不关心”,如果您决定需要使用其他参数,这将使您的生活更加轻松。
def foo(_name, _html_options, options)
  options.delete(:some_option)
  super
end

1
foo(_, _, a) 中,下划线仍然是一个有效的变量名,但是 _ 只被分配给第一个位置参数,第二个参数将被完全忽略。 - engineersmnky

4

_前缀不是语言特性,它没有任何特别之处,只是一种惯例。

在大多数情况下,开发人员想要表明一个变量未被使用,例如,在块中未使用的块变量。或者他们想要表明变量是模块或gem的内部变量,其他人不应该直接读取或修改此变量。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接