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
被调用时,则显示(外部)的修正值.
我明白那个
temp = @internalOnly
在Leaky:foo
方法中赋予引用@internalOnly
@internalOnly
在那之后,我不明白如何b = a.foo
最终引用@internalOnly
; 这似乎在很大程度上违反了Ruby的对象封装.这里发生了什么?
我在Ruby Language FAQ中找不到任何可以启发我的东西.(也许这是一个在常见问题 ...)
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)