“私有”、“公共”和“受保护的方法”之间有啥区别?

Posted

技术标签:

【中文标题】“私有”、“公共”和“受保护的方法”之间有啥区别?【英文标题】:What are the differences between "private", "public", and "protected methods"?“私有”、“公共”和“受保护的方法”之间有什么区别? 【发布时间】:2012-04-10 14:00:53 【问题描述】:

我正在学习 Ruby,并且已经到了让我感到困惑的地步。

我正在使用的书是在谈论privatepublicprotected methods,但我还是有点困惑。每个之间有什么区别?

【问题讨论】:

镐的第 2 版 :) 到目前为止一切都很好。 相关问题:***.com/q/3534449/38765 以及access-specifier 标签中可能存在的其他问题。 你应该改变答案。 【参考方案1】:

public 方法对所有人开放。至于privateprotected,我指的是“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”获取详细示例和说明。

简单地说,privatepublicprotected 方法之间的区别在于该方法在程序中的可见性,有点像只读、读写和几乎不可见。

与其他一些语言不同,您不能完全隐藏 Ruby 私有方法,您只能访问对象实例的私有方法,而不能访问类的任何其他对象实例。

当然,公共是完全可访问性,方法通常默认为公共,但有一些例外。

受保护的方法可以从同一类甚至子类的对象中访问,而私有方法则不然。

【讨论】:

私有方法通常可以从子类的对象中访问,只要它们是通过隐式接收器调用的(也就是说,它们的左侧没有任何点)。 因为我来自 Java 背景,Ruby 可见性设置需要一些保证和示例让我相信我真的明白了。大多数链接和解释都缺乏深度和示例,无法确定我了解所有方面。此答案中给出的链接易于阅读,阐明了各个方面,并且没有太多文字。我推荐它。感谢分享。【参考方案3】:

公共 - 可以从任何地方调用

Private - 不能在类范围之外调用该方法。对象只能向自己发送消息

例如:面包师的 bake 方法是公开的,但 break_eggs 是私有的

受保护 - 只要默认对象 self 是与您正在调用其方法的对象相同的类的实例,您就可以调用对象的受保护方法

例如:使用n 受保护方法,c1 可以要求c2 执行c2.n,因为c1c2 都是同一个类的实例

最后但同样重要的是:

继承:子类继承父类的方法访问规则

如果“class D

参考:http://www.amazon.com/Ruby-Rails-Techniques-Developers/dp/1932394699

【讨论】:

我是来问这个的:继承:子类继承其父类的方法访问规则 +1【参考方案4】:

让我解释一下 Privateprotected 方法在 Ruby 中的工作方式与大多数其他方法略有不同 编程语言。假设您有一个名为 Foo 的类和一个子类 SubFoo 。 在像 Java 这样的语言中,SubFoo 无法访问 Foo 定义的任何私有方法。 正如在解决方案中看到的,Ruby 没有提供任何方法来隐藏一个类的方法。 类。这样Ruby的私下就和Javaprotected一样。

进一步假设您有两个 Foo 类实例,ab。在语言中 像Javaab可以互相调用对方的private methods。在Ruby 中,您需要使用 protected method 为此。这是Rubyprivateprotected 方法的主要区别。

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 

【讨论】:

以上是关于“私有”、“公共”和“受保护的方法”之间有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 类中表示受保护的方法?

本地 和 实例 变量之间有啥区别

公共静态变量和私有静态变量之间的区别

用于存储简单数据的“公共静态”和“私有静态”之间的区别。啥是更好的? [复制]

如何在 python 中编写模块私有/受保护的方法?

私有/受保护的方法是不是应该进行单元测试? [关闭]