Answers:
protected
定义类或其子类的任何实例都可以调用这些方法。
private
方法只能在调用对象内调用。您不能直接访问另一个实例的私有方法。
这是一个快速的实际示例:
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
不能在private
这里。一定是protected
因为您需要它来支持显式接收器。典型的内部辅助方法通常是这样,private
因为它们不需要像这样被调用。
重要的是要注意,这与Java或C ++的工作方式不同。private
Ruby protected
中的Java 与Java / C ++中的相似,因为子类可以访问该方法。在Ruby中,没有办法像private
在Java中那样限制子类对方法的访问。
无论如何,Ruby中的可见性在很大程度上都是“推荐”,因为您始终可以使用以下方式访问方法send
:
irb(main):001:0> class A
irb(main):002:1> private
irb(main):003:1> def not_so_private_method
irb(main):004:2> puts "Hello World"
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> foo = A.new
=> #<A:0x31688f>
irb(main):009:0> foo.send :not_so_private_method
Hello World
=> nil
private
与protected
不得不做一个子类是否可以继承一个方法,但是实际上是关于可以从哪里调用该方法。谢谢!
send
吗?
self
。即使你不能打电话self.some_private_method
; 你必须调用private_method
与self
暗示。
在Ruby中,这些区别只是一个程序员对另一个程序员的建议。非公开方法是一种说法:“我保留更改此内容的权利;不要依赖它。” 但是,您仍然可以使用它的利器,send
并且可以调用任何您喜欢的方法。
# dwarf.rb
class Dwarf
include Comparable
def initialize(name, age, beard_strength)
@name = name
@age = age
@beard_strength = beard_strength
end
attr_reader :name, :age, :beard_strength
public :name
private :age
protected :beard_strength
# Comparable module will use this comparison method for >, <, ==, etc.
def <=>(other_dwarf)
# One dwarf is allowed to call this method on another
beard_strength <=> other_dwarf.beard_strength
end
def greet
"Lo, I am #{name}, and have mined these #{age} years.\
My beard is #{beard_strength} strong!"
end
def blurt
# Not allowed to do this: private methods can't have an explicit receiver
"My age is #{self.age}!"
end
end
require 'irb'; IRB.start
然后,您可以运行ruby dwarf.rb
并执行以下操作:
gloin = Dwarf.new('Gloin', 253, 7)
gimli = Dwarf.new('Gimli', 62, 9)
gloin > gimli # false
gimli > gloin # true
gimli.name # 'Gimli'
gimli.age # NoMethodError: private method `age'
called for #<Dwarf:0x007ff552140128>
gimli.beard_strength # NoMethodError: protected method `beard_strength'
called for #<Dwarf:0x007ff552140128>
gimli.greet # "Lo, I am Gimli, and have mined these 62 years.\
My beard is 9 strong!"
gimli.blurt # private method `age' called for #<Dwarf:0x007ff552140128>
age=
,则可以(必须)调用它self
以将其与局部变量分开。
gimli.greet
,gimli
不是调用方,而是接收方。调用方是“顶级执行环境”,它实际上是的临时实例Object
。试试这个:ruby -e 'p self; p self.class'
如果方法在Ruby中是私有的,则不能由显式接收器(对象)调用该方法。只能隐式调用。可以由描述它的类以及该类的子类隐式调用它。
以下示例将更好地说明它:
1)具有私有方法class_name的Animal类
class Animal
def intro_animal
class_name
end
private
def class_name
"I am a #{self.class}"
end
end
在这种情况下:
n = Animal.new
n.intro_animal #=>I am a Animal
n.class_name #=>error: private method `class_name' called
2)动物的一个子类,称为两栖类:
class Amphibian < Animal
def intro_amphibian
class_name
end
end
在这种情况下:
n= Amphibian.new
n.intro_amphibian #=>I am a Amphibian
n.class_name #=>error: private method `class_name' called
如您所见,私有方法只能隐式调用。显式接收者不能调用它们。由于相同的原因,私有方法不能在定义类的层次结构之外调用。
如果某个方法在Ruby中受保护,那么定义类及其子类都可以隐式调用该方法。另外,只要接收者是self或与self属于同一类,它们也可以由显式接收者调用:
1)具有受保护方法protect_me的动物类
class Animal
def animal_call
protect_me
end
protected
def protect_me
p "protect_me called from #{self.class}"
end
end
在这种情况下:
n= Animal.new
n.animal_call #=> protect_me called from Animal
n.protect_me #=>error: protected method `protect_me' called
2)从动物类继承而来的哺乳动物类
class Mammal < Animal
def mammal_call
protect_me
end
end
在这种情况下
n= Mammal.new
n.mammal_call #=> protect_me called from Mammal
3)从动物类继承的两栖类(与哺乳动物类相同)
class Amphibian < Animal
def amphi_call
Mammal.new.protect_me #Receiver same as self
self.protect_me #Receiver is self
end
end
在这种情况下
n= Amphibian.new
n.amphi_call #=> protect_me called from Mammal
#=> protect_me called from Amphibian
4)称为树的类
class Tree
def tree_call
Mammal.new.protect_me #Receiver is not same as self
end
end
在这种情况下:
n= Tree.new
n.tree_call #=>error: protected method `protect_me' called for #<Mammal:0x13410c0>
考虑一下Java中的私有方法。当然,可以从同一类中调用它,但是也可以由同一类的另一个实例调用它:
public class Foo {
private void myPrivateMethod() {
//stuff
}
private void anotherMethod() {
myPrivateMethod(); //calls on self, no explicit receiver
Foo foo = new Foo();
foo.myPrivateMethod(); //this works
}
}
因此,可以说,如果调用者是同一类的不同实例,那么实际上可以从“外部”访问我的私有方法。实际上,这似乎使它看起来不是那么私密。
另一方面,在Ruby中,私有方法确实意味着仅对当前实例私有。这就是删除显式接收器选项所提供的。
另一方面,我当然应该指出,在Ruby社区中,根本不使用这些可见性控件是很普遍的,因为Ruby提供了无论如何都可以绕开它们的方法。与Java世界不同,趋势是使所有内容都可以访问并信任其他开发人员不要搞砸。
私有方法可以被Ruby的子类访问的部分原因是,具有类的Ruby继承是对Module的精打细算-在Ruby中,类实际上是提供继承的一种模块,等等。
http://ruby-doc.org/core-2.0.0/Class.html
这意味着基本上子类会“包含”父类,以便在子类中也有效地定义父类的函数(包括私有函数)。
在其他编程语言中,调用方法涉及将方法名称冒泡到父类层次结构中,并找到响应该方法的第一个父类。相反,在Ruby中,当父类层次结构仍然存在时,父类的方法直接包含在已定义的子类的方法列表中。
Java与Ruby的访问控制的比较:如果方法在Java中声明为私有,则该方法只能由同一类中的其他方法访问。如果方法被声明为受保护的,则可以由同一包中存在的其他类以及其他包中的该类的子类访问该方法。当一种方法公开时,每个人都可以看到。在Java中,访问控制可见性概念取决于这些类在继承/包层次结构中的位置。
而在Ruby中,继承层次结构或包/模块不适合。关于哪个对象是方法的接收者。
对于Ruby中的私有方法,永远不能使用显式接收器来调用它。我们(只能)使用隐式接收器调用private方法。
这也意味着我们可以从在其声明的类以及该类的所有子类中调用私有方法。
class Test1
def main_method
method_private
end
private
def method_private
puts "Inside methodPrivate for #{self.class}"
end
end
class Test2 < Test1
def main_method
method_private
end
end
Test1.new.main_method
Test2.new.main_method
Inside methodPrivate for Test1
Inside methodPrivate for Test2
class Test3 < Test1
def main_method
self.method_private #We were trying to call a private method with an explicit receiver and if called in the same class with self would fail.
end
end
Test1.new.main_method
This will throw NoMethodError
您永远不能从定义了它的类层次结构之外调用私有方法。
可以使用隐式接收器来调用受保护的方法,就像private一样。此外,如果接收者是“自身”或“同一类的对象”,则显式接收者也可以(仅)调用受保护的方法。
class Test1
def main_method
method_protected
end
protected
def method_protected
puts "InSide method_protected for #{self.class}"
end
end
class Test2 < Test1
def main_method
method_protected # called by implicit receiver
end
end
class Test3 < Test1
def main_method
self.method_protected # called by explicit receiver "an object of the same class"
end
end
InSide method_protected for Test1
InSide method_protected for Test2
InSide method_protected for Test3
class Test4 < Test1
def main_method
Test2.new.method_protected # "Test2.new is the same type of object as self"
end
end
Test4.new.main_method
class Test5
def main_method
Test2.new.method_protected
end
end
Test5.new.main_method
This would fail as object Test5 is not subclass of Test1
Consider Public methods with maximum visibility
摘要
公开:公开方法具有最大的可视性
受保护的:受保护的方法可以使用隐式接收器来调用,就像私有方法一样。此外,如果接收者是“自身”或“同一类的对象”,则显式接收者也可以(仅)调用受保护的方法。
私有:对于Ruby中的私有方法,永远不能使用显式接收器调用它。我们(只能)使用隐式接收器调用private方法。这也意味着我们可以从在其声明的类以及该类的所有子类中调用私有方法。
First Three types of access specifiers and those define thier scope.
1.Public -> Access anywhere out side the class.
2.Private -> Can not access outside the class.
3.Protected -> This Method not access anywhere this method define
scope.
But i have a solution for this problem for all method how to access explain in depth.
class Test
attr_reader :name
def initialize(name)
@name = name
end
def add_two(number)
@number = number
end
def view_address
address("Anyaddress")
end
private
def address(add)
@add = add
end
protected
def user_name(name)
# p 'call method'
@name = name
end
end
class Result < Test
def new_user
user_name("test355")
end
end
Object
允许所有实例调用其他实例的私有方法Object
,那么可能会说诸如此类5.puts("hello world")
。