《反私》setter 方法的属性 [英] "Anti-private" property of setter method

查看:61
本文介绍了《反私》setter 方法的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Getter 方法可以在没有显式接收器的情况下使用,除非存在同名的局部变量:

Getter methods can be used without an explicit receiver unless there is a local variable with the same name:

class A; attr_reader :foo end
A.new.instance_eval do
  @foo = :foo
  p foo
end
# => :foo

当存在同名的局部变量时,这将不成立,因为在有歧义时,解释为局部变量比作为方法调用具有优先权.

This will not hold when there is a local variable with the same name, due to the principle that interpretation as a local variable has priority than as a method call whenever there is an ambiguity.

class A; attr_reader :foo end
A.new.instance_eval do
  foo = :bar
  @foo = :foo
  p foo
end
# => :bar

然而,setter 方法不能在没有显式接收器的情况下使用,即使在所讨论的表达式之前没有分配同名的局部变量:

However, setter methods cannot be used without an explicit receiver even when a local variable with the same name is not assigned prior to the expression in question:

class A; attr_writer :foo end
A.new.instance_eval do
  foo = :foo  # <= No local variable named `foo` has been assigned before this point
  p @foo
end
# => nil

setter 方法的这种反私有"属性如何证明?

How is this "anti-private" property of setter method justified?

推荐答案

如果 ruby​​ 将你最后一条语句中的赋值解释为对 self 的赋值,你将无法设置局部变量.

If ruby interpreted your assignment in your last statement as an assignment to self, you would have no way left to set a local variable.

解释器处理的方式没有歧义:没有 self 的赋值总是局部变量,对 self 的赋值总是试图在对象上使用 writer.

The way it is leaves no ambiguity for the interpreter to deal with: assignments without self are always local variables, assignments to self are always trying to use a writer on the object.


解释器必须查找上下文编写器方法并通过编写器分配它(如果有),这几乎肯定会对性能产生负面影响

The interpreter would have to look up the contexts writer methods and assign it via the writer if there is one, which almost certainly would have a negative impact on performance

class A
  attr_writer :foo
end

A.new.instance_eval do
  # for each of these assignments, the interpreter has to look up if there's
  # a writer method defined
  foo = 'bar' 
  bar = 'baz'
  fib = 'buz'
end

这也会让程序员在分配局部变量之前找出他所在上下文的每个 setter 方法,以确保他不会无意中使用 setter,这是一项相当愚蠢的任务.

It would also leave the programmer with the rather stupid task to find out every setter method of the context he's in before assigning local variables to make absolutely sure he does not unintentionally use a setter.

class C
  attr_writer :something
end

class B < C
  attr_writer :foo
end

class A < B
  attr_writer :bar
end

A.new.instance_eval
  something = 'something' 
  #you just (almost certainly with no intention) assigned a value to an attribute
end

另外,你的问题是:

setter 方法不能在没有显式接收器的情况下使用,即使同名的局部变量不会在有问题的表达:

setter methods cannot be used without an explicit receiver even when a local variable with the same name is not assigned prior to the expression in question:

如果反过来,则不能在所讨论的表达式之前分配具有相同名称的局部变量,因为分配将使用 setter(如本答案的第一段所述)

If it were the other way around, you could not assign a local variable with the same name prior to the expression in question, because the assignment would use the setter (as stated in the first paragraph of this answer)

关于属性方法使用的实现/对变量的访问:Getter 和 Setter 使用实例变量.所以,例如 attr_accessor 实际上定义了这样的东西:

Concerning the implementation / the access to variables the attribute methods use: Getter and Setters work with instance variables. So, for example attr_accessor actually defines something like this:

 def foo
   @foo
 end

 def foo=(data)
   @foo = data
 end

那么,属性被声明为实例变量而不是局部变量,为什么程序员可以像局部变量一样分配它?这会留下错误的印象,即您可以通过分配局部变量来分配对象的实例变量.如果 ruby​​ 这样做,几乎肯定会导致严重的内存管理问题.简而言之:foo = 'bar'@foo = 'bar' 不一样,正是因为 attr 方法使用@foo = 'bar',你不能通过使用 foo = 'bar' 来调用它们.

So, the attribute is declared as a instance variable and not as a local variable, why should the programmer be able to assign it like a local variable? This would leave the wrong impression that you could assign instance variables of an object via assigning local variables. If ruby would do this, it would almost certainly lead to a serious memory management problem. To make it short: foo = 'bar' and @foo = 'bar' are not the same, and exactly because the attr methods use @foo = 'bar', you can not call them via using foo = 'bar'.

这篇关于《反私》setter 方法的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆