覆盖哈希并将[]运算符设为私有 - 不能再使用|| =

Kar*_*k T 6 ruby overriding operators

测试代码:

class PrivHash < Hash
  def set(key, val)
     self[key] = val
  end
  def set_maybe(key, val)
    self[key] ||= val
  end
  private
  def []= key, value 
  end
  def [] key
    super            
  end
end
Run Code Online (Sandbox Code Playgroud)

有了这个代码,我都期盼setset_maybe工作.但是,只有set工作并set_maybe失败:

[30] pry(#<TranslationInfo>):1> ph.set_maybe(:a, 1)
NoMethodError: private method `[]' called for {:a=>2}:#Class:0x007f99c5924c38>::PrivHash 
from (pry):56:in `set_maybe'
Run Code Online (Sandbox Code Playgroud)

我认为这self[:b] ||= <x>只是语法糖self[:b] || self[:b] = <x>,但我想这不是因为这有效.

什么错误我是为什么我得到这个错误..我从类中执行此,所以为什么我得到私有方法错误?

Jör*_*tag 3

目前,私有方法的处理有点混乱。

原来的规则是:

私有方法只能在没有显式接收者的情况下调用。

这是一个很好的、简单的、容易理解的规则。它也是一个静态规则,即不需要运行代码就可以检查,事实上,它甚至是一个语法规则,它甚至不需要复杂的静态分析,可以在解析器中检查。

然而,很快人们就注意到,这条规则使得调用私有 setter 变得不可能,因为没有显式接收者就无法调用 setter(foo = bar是设置局部变量,而不是调用 setter)。因此,规则被扩展:

私有方法只能在没有显式接收器的情况下调用,除非方法调用是赋值方法调用,在这种情况下,只要显式接收器是文字伪变量,也可以使用显式接收器调用该方法self

这允许您使用文字值的显式接收器调用私有设置器self

self.foo = bar
Run Code Online (Sandbox Code Playgroud)

但不是动态值self

baz = self
baz.foo = bar # NoMethodError: private method `foo=' called
Run Code Online (Sandbox Code Playgroud)

这仍然保留了可以在解析时检测到私有方法调用的属性。

两年前,我提交了一个关于缩写方法分配不起作用的错误,即:

self.foo += bar # NoMethodError
Run Code Online (Sandbox Code Playgroud)

通过再次扩展私有方法调用的规则来修复该错误(现在规则已经变得如此复杂,我不打算详细说明)。

然而,仍然有很多情况没有被现有规则涵盖,这些方法在语法上根本无法在没有显式接收者的情况下被调用,因此不能是私有的:

self[foo]
!self
self + foo
Run Code Online (Sandbox Code Playgroud)

ETC。

其中一些已经修复,一些还没有。问题是该规则现在变得如此复杂,以至于很难正确实施。有人建议将规则更改为如下内容:

私有方法只能在没有显式接收器或显式接收器(即字面量伪变量)的情况下调用self

这是一个很好、简单、易于理解的规则,可以在解析时进行静态检查,并且没有我们当前拥有的复杂异常和极端情况。然而,据我所知,它尚未实施。