为什么Ruby类允许通过方法返回来访问实例变量?

Gna*_*wme 0 ruby encapsulation reference instance-variables

我有一个同事的Ruby代码:

class Leaky

   def initialize
      @internalOnly = [[1, 2, 3], [3, 4, 5]]
   end

   def foo
      if 5 > 4
         temp = @internalOnly
      end
   end

   def printInternal
      puts " here is my @internalOnly: #{@internalOnly}"
   end

end

a = Leaky.new
a.printInternal

b = a.foo  # 1) Gets Leaky:@internal!
b[1] = 666 # 2) Modifies it!

a.printInternal
Run Code Online (Sandbox Code Playgroud)

它产生这个输出:

 here is my @internalOnly: [[1, 2, 3], [3, 4, 5]]
 here is my @internalOnly: [[1, 2, 3], 666]
Run Code Online (Sandbox Code Playgroud)

在语句中# 1),Ruby显然返回了对Leaky实例变量的引用@internalOnly,然后它用于修改@internalOnly语句#2).

Leaky:printInternal被调用时,则显示(外部)的修正值.

我明白那个

  1. 变量是Ruby中的引用,因此temp = @internalOnlyLeaky:foo方法中赋予引用@internalOnly
  2. Ruby返回此表达式的值 - 分配给的Array @internalOnly

在那之后,我不明白如何b = a.foo最终引用@internalOnly; 这似乎在很大程度上违反了Ruby的对象封装.这里发生了什么?

我在Ruby Language FAQ中找不到任何可以启发我的东西.(也许这是一个在常见问题 ...)

7st*_*tud 5

1)foo()只是一个具有奇怪名称的访问器方法,与以下内容没有区别:

def internalOnly
  @internalOnly
end
Run Code Online (Sandbox Code Playgroud)

2)类中的任何方法都可以访问实例的私有变量,即@variables.

3)方法返回最后执行的语句的'value'.

4)赋值语句的值是右侧.

在那之后,我不明白b = a.foo如何以对@internalOnly的引用结束

变量是Ruby中的引用

因为a.foo返回对数组的引用,该引用被赋值给b.结果,两个变量@internalOnly和b引用相同的数组.

这似乎在很大程度上违反了Ruby的对象封装.这里发生了什么?

好吧,程序员允许这种情况发生.如果不是这样,那么代码可以像这样重写:

   def foo
      if 5 > 4
         @internalOnly.dup
      end
   end
Run Code Online (Sandbox Code Playgroud)

但是,您应该知道任何具有足够ruby知识的程序员总是可以访问实例的私有变量:

class Dog
  attr_reader :friends

  def initialize(friends)
    @friends = friends
  end
end

d = Dog.new(['cat', 'bird', 'mouse'])

x = d.instance_variable_get(:@friends)
x[0] = 'velociraptor'

p d.friends

--output:--
["velociraptor", "bird", "mouse"]
Run Code Online (Sandbox Code Playgroud)