gpt4 book ai didi

ruby - 为什么 self.method_name 无法访问私有(private)方法?其中只有 private method_name 可以在任何方法中访问 ruby​​ 中的私有(private)方法

转载 作者:行者123 更新时间:2023-12-03 08:28:34 26 4
gpt4 key购买 nike

class Person
def one
@var = 99
self.two
end
private
def two
p @var
end
end
p=Person.new
p.one

当我运行此代码时,我收到错误消息main.rb:4:in one': 私有(private)方法 two' 调用 # (NoMethodError)
来自 main.rb:12:in `'

class Person
def one
@var = 99
two
end
private
def two
p @var
end
end
p=Person.new
p.one

当我运行这个时,我得到的输出为 99。因此,当 p.one 调用时,它会转到方法一,当它发现方法二没有任何接收者对象(这意味着方法二以 self 作为对象)时执行它,并且成功执行该方法。

但是当我手动给出 self.two 时,它给了我错误,为什么?

两个VS self.two的方法调用有什么区别?

最佳答案

why self.method_name cannot access private method ?

因为这就是 private 的定义方式,至少在您使用的旧版 Ruby 中是这样。

在当前版本的 Ruby 中可以。您所描述的行为仅存在于旧版本的 Ruby 中。

如果我使用我的 Ruby 安装(由 YARV 3.0.0 实现的 Ruby 3.0.0)运行您的代码,我不会收到错误。

以下是private历史上的定义方式:

A private method can only be called without a receiver.

例如,参见 ISO/IEC 30170:2012 Information technology — Programming languages — Ruby specification 的第 13.3.5.3 节私有(private)方法 :

A private method cannot be invoked with an explicit receiver, i.e., a private method cannot be invoked if a primary-expression or a chained-method-invocation occurs at the position which corresponds to the method receiver in the method invocation

但是请注意,这并不是故事的全部。

在此规则下如何调用私有(private)属性编写器?答案是:你不能!您不能使用 self.foo = bar 因为您不允许使用显式接收器,并且您不能使用 foo = bar 因为这是对局部变量 foo 而不是对属性编写器 foo= 的调用。

所以,这个规则实际上有一个异常(exception):

A private method can only be called without a receiver, unless it is an attribute writer, then it can also be called with a receiver that is the literal pseudo-variable self.

请注意,它必须是文字伪变量self。它不能是计算结果为同一对象的任何任意表达式。

即这是允许的:

self.foo = bar

但这不是:

this = self
this.foo = bar
# private method `foo=' called for #<…> (NoMethodError)

ISO Ruby 语言规范的确切文本是:

A private method cannot be invoked with an explicit receiver, i.e., a private method cannot be invoked if a primary-expression or a chained-method-invocation occurs at the position which corresponds to the method receiver in the method invocation, except for a method invocation of any of the following forms where the primary-expression is a self-expression.

  • single-method-assignment
  • abbreviated-method-assignment
  • single-indexing-assignment
  • abbreviated-indexing-assignment

但是,这仍然不能解决所有问题:运算符怎么样,例如 self + bar!self?名称是诸如 class 之类的保留字的方法怎么样?

提议的规则变得越来越复杂。有关一些见解,请参阅以下有关 Ruby 问题跟踪器的讨论: Bug #9907 Abbreviated method assignment with private attr_writer/attr_reader does not work. [免责声明:我是提交该错误的人。]

要使此工作正常进行,您必须将规则更改为类似的内容

A private method can only be called without a receiver, unless it is an attribute writer or an operator, then it can also be called with a receiver that is the literal pseudo-variable self, including in an abbreviated method assignment.

如您所见,规则变得相当复杂。

提出了一个更简单的规则,现在从 Ruby 2.7 开始实现:

现在的规则是:

A private method can only be called without a receiver or with an explicit receiver that is the literal pseudo-variable self.

您可能会问自己,为什么不使用这个更简单的规则?

A private method can only be called with the receiver self.

原因是旧规则、中间规则和新规则 can be decided statically, in fact even syntactically at parse time ,而这个非常简单的规则却不能。

关于ruby - 为什么 self.method_name 无法访问私有(private)方法?其中只有 private method_name 可以在任何方法中访问 ruby​​ 中的私有(private)方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65867395/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com