“私有”、“公共”和“受保护的方法”之间有啥区别?
Posted
技术标签:
【中文标题】“私有”、“公共”和“受保护的方法”之间有啥区别?【英文标题】:What are the differences between "private", "public", and "protected methods"?“私有”、“公共”和“受保护的方法”之间有什么区别? 【发布时间】:2012-04-10 14:00:53 【问题描述】:我正在学习 Ruby,并且已经到了让我感到困惑的地步。
我正在使用的书是在谈论private
、public
和protected methods
,但我还是有点困惑。每个之间有什么区别?
【问题讨论】:
镐的第 2 版 :) 到目前为止一切都很好。 相关问题:***.com/q/3534449/38765 以及access-specifier 标签中可能存在的其他问题。 你应该改变答案。 【参考方案1】:public
方法对所有人开放。至于private
与protected
,我指的是“Ruby Private Methods vs. Protected Methods”:
'private' 和 'protected' 方法有什么区别 红宝石?在 Ruby 中,'private' 和 'protected' 方法是 不能使用私有方法调用 显式接收器,而受保护的方法可以。什么是 '显式接收器',你问?显式接收者是对象 正在接收消息。在下面的示例中,我们有一个接收器 ('parent') 和一个方法 ('get_name')。 “父”对象是 接收执行“get_name”方法的指令。
【讨论】:
这是一个很好的例子,说明如何用“显式接收器”等不必要的抽象概念以复杂的方式解释简单的行为。 50% 的答案是关于解释什么是显式接收器,即可以用来回答问题的空间。 这个答案没有解释引用的作者所说的“显式接收器”是什么意思:源代码中可见的接收器,它和方法名称之间有一个点。唯一的另一种可能性(我认为在 Ruby 语法中)是调用不带点的方法,因此 Ruby 通过遵循约定来提供接收器。这称为使用“隐式接收器”调用方法。 @shredding 我非常不同意这是一种解释简单行为的复杂方式。相反。他用 15 个字总结了 主要 的区别!说真的——试着打败它!我成为 Rubyist 大约 10 年了,我从未见过更简洁的解释来解释两者的区别。就我个人而言,我发现这个答案很有帮助——而且比这里提供的大多数其他答案更简单(包括一个更简单、更优雅的例子)。作者解释的事实澄清了明确的接收者对于那些不知道的人来说不应该算作他。 以下示例不再可用。链接烂人,很烂 @shredding 你能发表你更好的解释吗?【参考方案2】:查看“Ruby Programming/Syntax/Classes”获取详细示例和说明。
简单地说,private
、public
和 protected
方法之间的区别在于该方法在程序中的可见性,有点像只读、读写和几乎不可见。
与其他一些语言不同,您不能完全隐藏 Ruby 私有方法,您只能访问对象实例的私有方法,而不能访问类的任何其他对象实例。
当然,公共是完全可访问性,方法通常默认为公共,但有一些例外。
受保护的方法可以从同一类甚至子类的对象中访问,而私有方法则不然。
【讨论】:
私有方法通常可以从子类的对象中访问,只要它们是通过隐式接收器调用的(也就是说,它们的左侧没有任何点)。 因为我来自 Java 背景,Ruby 可见性设置需要一些保证和示例让我相信我真的明白了。大多数链接和解释都缺乏深度和示例,无法确定我了解所有方面。此答案中给出的链接易于阅读,阐明了各个方面,并且没有太多文字。我推荐它。感谢分享。【参考方案3】:公共 - 可以从任何地方调用
Private - 不能在类范围之外调用该方法。对象只能向自己发送消息
例如:面包师的 bake
方法是公开的,但 break_eggs
是私有的
受保护 - 只要默认对象 self
是与您正在调用其方法的对象相同的类的实例,您就可以调用对象的受保护方法
例如:使用n
受保护方法,c1
可以要求c2
执行c2.n
,因为c1
和c2
都是同一个类的实例
最后但同样重要的是:
继承:子类继承父类的方法访问规则如果“class D
参考:http://www.amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699
【讨论】:
我是来问这个的:继承:子类继承其父类的方法访问规则 +1【参考方案4】:让我解释一下
Private
和 protected
方法在 Ruby
中的工作方式与大多数其他方法略有不同
编程语言。假设您有一个名为 Foo
的类和一个子类 SubFoo
。
在像 Java
这样的语言中,SubFoo
无法访问 Foo 定义的任何私有方法。
正如在解决方案中看到的,Ruby 没有提供任何方法来隐藏一个类的方法。
类。这样Ruby
的私下就和Java
的protected
一样。
进一步假设您有两个 Foo 类实例,a
和 b
。在语言中
像Java
、a
和b
可以互相调用对方的private methods
。在Ruby
中,您需要使用
protected method
为此。这是Ruby
中private
和protected
方法的主要区别。
class Foo
private
def pri
'hey I am private of Foo'
end
protected
def prot
'Hey I am protected of Foo'
end
end
现在是Foo
的子类
class SubFoo < Foo
def call_pri_of_foo
pri
end
def call_prot_of_foo
prot
end
end
现在调用 SubFoo
内的访问器
> sub_foo = SubFoo.new
=> #<SubFoo:0x00000002b56ad8>
> sub_foo.call_pri_of_foo
=> "hey I am private of Foo"
> sub_foo.call_prot_of_foo
=> "Hey I am protected of Foo"
到这里;好像没什么区别
next_sub_foo = SubFoo.new
=> #<SubFoo:0x00000002b1a0b0>
def next_sub_foo.access_private(child_of_sub_foo)
child_of_sub_foo.pri
end
def next_sub_foo.access_protected(child_of_sub_foo)
child_of_sub_foo.prot
end
现在调用访问器
> next_sub_foo.access_private(sub_foo)
# => NoMethodError: private method `pri' called for #<SubFoo:0x00000002b56ad8>
但它可以访问其兄弟姐妹的受保护方法
> next_sub_foo.access_protected(sub_foo)
# => "Hey I am protected of Foo"
你也可以看@tenderlove
的博客更清晰的图片http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html
【讨论】:
【参考方案5】:研究了我从 here 获取的信息,我通过错误扩展了解释,并且在我看来,这有助于理解为什么以及如何使用受保护而不是私有。
1) 受保护:
第12行crash,因为接收到的参数来自另一个类,错误信息很清楚:
v.rb:12:in `==': undefined method `sku' for "Object of another class ==> crash":String (NoMethodError)
2) 私人:
如果从第 8 行和第 12 行删除 self,并且我将 protected 更改为 private,则会崩溃,因为在第 12 行,other 不知道 sku 是什么:
v.rb:12:in `==': private method `sku' called for #<Product:0x00000001574e68 @name="Bread", @quantity=1> (NoMethodError)
程序:
class Product
attr_accessor :name, :quantity
def initialize(name)
@name = name
@quantity = 1
puts "The SKU is #self.sku"
end
def == (other)
self.sku == other.sku
end
protected
def sku
name.crypt("yo")
end
end
milk1 = Product.new("Milk")
milk2 = Product.new("Milk")
bread = Product.new("Bread")
puts milk1 == bread
puts milk1 == milk2
puts milk1 == "Object of another class ==> crash"
【讨论】:
【参考方案6】:我认为,如果您无法理解这个概念,那么分解显式接收器很重要。
显式接收者是接受消息的对象。
person.get_name
person 是接收者,方法 "get_name" 向对象 "person" 发出指令以执行方法 "get_name"。
class Person
attr_accessor :first_name, :last_name
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
puts "And #phone_number" # Private method called when initialized
end
private
def phone_number
return "XXX-XXX-XXXX"
end
end
p p1 = Person.new("mike", "jones")
p p1.phone_number # Not within the context of the object instance.
当一个方法是私有的时,它只能被定义在其类中的对象内部的其他方法使用。
【讨论】:
【参考方案7】:区别在于可见性以及它们如何受到继承的影响:
可见性:
|| 任何地方 || Public 可以从类的内部和外部访问。
|| 课堂内 || Private 和 Protected 都只能从类内部访问。
Protected 和 Private 之间的相似性:
两者都可以通过公共方法从类外部访问。受保护和私有之间的区别是:
不能用接收器调用私有方法(甚至不能用#self)。 除非 ...调用 PRIVATE SETTER 方法。如果您尝试删除接收器,Ruby 将创建一个局部变量。在这种情况下,自我是必须的。
Protected 可能使用也可能不使用 self。
Protected 可以访问来自同一类的另一个对象的受保护方法,Private 不能。
说到继承:
只能在子类上隐式调用私有方法(只是方法的名称)但不能显式调用(使用#self)。
Protected 可以两种方式调用(带或不带#self || 隐式或显式)。
以下代码示例:
class Dog
attr_accessor :name, :age
def initialize(n, a)
self.name = n
self.age = a
end
def accessing_private
"#self.name in human years is #human_years. This is secret!"
end
def accessing_protected
"Will this work? " + a_protected_method
end
def eat_more_than(other)
# accessing other instance's protected method from the same class
daily_diet < other.daily_diet
"#name eats more than #other.name"
end
def boy
gender_method("boy") # accessing private setter method
end
protected
def daily_diet
age * 2 # the younger, the more they have to eat
end
def a_protected_method
"Yes, I'm protected!"
end
private
attr_writer :gender
def gender_method(gender)
self.gender = gender # private setter method requires self
"#name is a #gender"
end
def human_years
age * 8
end
end
# Create the first object of Dog
blake = Dog.new("Blake", 5)
p blake.accessing_private # "Blake in human years is 16. This is secret!"
p blake.accessing_protected # "Will this work? Yes, I'm protected!"
# Create the second object of Dog
jackson = Dog.new("Jackson", 1)
# Below, protected methods from different objects of the same type/class
# are proven to share access
p jackson.eat_more_than(blake) # true -> "Jackson eats more than Blake"
# Below, accessing private setter method through a public method.
p blake.boy # Blake is a boy
【讨论】:
以上是关于“私有”、“公共”和“受保护的方法”之间有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章