public
- 可以被任何对象访问(例如Obj.new.public_method
)protected
- 只能从对象本身以及任何子类中访问private
- 与保护方法相同,但在子类中不存在该方法
protected
和private
的行为相同,唯一的区别在于您不能使用显式接收器调用private
方法(即self.protected_method
可以,但self.private_method
不行)。这有什么意义?什么情况下您不想通过显式接收器调用方法?
public
- 可以被任何对象访问(例如Obj.new.public_method
)protected
- 只能从对象本身以及任何子类中访问private
- 与保护方法相同,但在子类中不存在该方法protected
和private
的行为相同,唯一的区别在于您不能使用显式接收器调用private
方法(即self.protected_method
可以,但self.private_method
不行)。protected
方法可以被定义类或其子类的任何实例调用。
private
方法只能从调用对象内部调用。无法直接访问另一个实例的私有方法。
这里是一个快速的实际例子:
def compare_to(x)
self.some_method <=> x.some_method
end
some_method
不能在此处声明为private
。 它必须是protected
,因为您需要它来支持显式的接收器。 您通常可以将典型的内部辅助方法定义为private
,因为它们从不需要像这样被调用。
重要的是要注意,这与Java或C ++的工作方式不同。 在Ruby中,private
类似于Java / C ++中的protected
,因为子类可以访问该方法。 在Ruby中,没有办法像Java中的private
那样限制从其子类访问方法。
在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
与子类是否能继承方法有关,但实际上它们决定了方法可以从哪里调用。谢谢! - Kyle Slatterysend
吗? - Cyoceself
调用。即使是您自己也不能调用self.some_private_method
;您必须使用隐含的self
调用private_method
。
在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
来调用它以将其与局部变量分开。 - iGELgimli.greet
时,gimli
不是调用者,而是接收者。调用者是“顶层执行环境”,实际上是 Object
的一个临时实例。试试这个:ruby -e 'p self; p self.class'
- Kelvin如果一个方法在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) 一个名为Amphibian的Animal子类:
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) 一个名为Tree的类
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>
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
}
}
@freddie = Person.new
@freddie.hows_it_going?
# => "oh dear, i'm in great pain!"
class Person
# public method
def hows_it_going?
how_are_your_underpants_feeling?
end
private
def how_are_your_underpants_feeling? # private method
puts "oh dear, i'm in great pain!"
end
end
考虑到这是一个公共方法,我们可以向Freddie询问事情的进展情况,这是完全合法的,并且是正常和被接受的。
但是...唯一知道Freddie内裤状况的人是Freddie本人。让随机陌生人去伸手进Freddie的内裤是绝对不行的 - 不行,不行 - 这非常私人化,我们不希望将私人信息暴露给外部世界。换句话说,我们可能不想将可变数据暴露给世界上的任何调用者。有人可能会改变一个值,而我们将面临着试图发现错误来源的痛苦。
@freddie.how_are_your_underpants_feeling?
# => # NoMethodError: private method `how_are_your_underpants_feeling?' called
考虑以下内容:
class Person
protected
def hand_over_the_credit_card! # protected method
puts "Lawd have mercy. Whatever. Here it is: 1234-4567-8910"
end
end
class Rib < Person
end
class Wife < Rib # wife inherits from Rib
def i_am_buying_another_handbag_with_your_card(husband)
husband.hand_over_the_credit_card! # equalityInAction
end
end
@husband = Person.new
@mrs = Wife.new
@mrs.i_am_buying_another_handbag_with_your_card(@husband)
# => puts "Lawd have mercy. Whatever. Here it is: 1234-4567-8910"
我们对于 mrs
能够获取到我们的信用卡信息还算可以接受,因为 mrs
是我们的血脉,继承自 Person,所以她可以把钱花在一些鞋子上等等,但我们不希望其他任意个人可以获取到我们的信用卡信息。
如果我们试图在子类外部执行这个操作,它将会失败:
@mrs = Wife.new
@mrs.gimme_your_credit_card!
# => protected method hand_over_the_credit_card! called for #<Wife:0x00005567b5865818> (NoMethodError)
http://ruby-doc.org/core-2.0.0/Class.html
这意味着子类“包含”父类,因此实际上子类中定义了父类的函数,包括私有函数。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
您不能从定义它的类层次结构之外的地方调用私有方法。
受保护的方法可以像私有方法一样使用隐式接收器进行调用。此外,如果接收器是“self”或“同一类的对象”,则还可以通过显式接收器(仅限)调用受保护的方法。
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
摘要
公共方法:公共方法具有最大的可见性。
受保护的方法:受保护的方法可以通过隐式接收器进行调用,就像私有方法一样。此外,只有当接收器为“self”或“与同一类的对象”时,才可以通过显式接收器调用受保护的方法。
私有方法:对于 Ruby 中的私有方法,它永远无法使用显式接收器进行调用。我们只能使用隐式接收器调用私有方法。这也意味着我们可以从声明私有方法的类以及该类的所有子类中调用私有方法。
首先,有三种访问修饰符,它们定义了它们的作用域。
但我有一个解决方案,适用于所有方法,如何访问将进行深入解释。
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")
。请注意,此处涉及私有方法的概念。 - sepp2k