42

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

我正在使用的书正在谈论private,publicprotected methods,但我仍然有点困惑。每个之间有什么区别?

4

7 回答 7

45

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

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

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

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

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

最后但并非最不重要:

  • 继承:子类继承其超类的方法访问规则

如果“class D < C”,则 D 将表现出与 C 实例相同的访问行为

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

于 2014-02-05T11:51:27.567 回答
33

public方法对所有人开放。至于privatevs protected,我指的是《Ruby Private Methods vs. Protected Methods》:

Ruby 中的“私有”和“受保护”方法有什么区别?在 Ruby 中,“私有”和“受保护”方法之间的主要区别在于,私有方法不能用显式接收者调用,而受保护方法可以。你问什么是“显式接收器”?显式接收者是接收消息的对象。在下面的例子中,我们有一个接收者('parent')和一个方法('get_name')。“父”对象正在接收执行“get_name”方法的指令。

于 2012-03-27T02:58:56.717 回答
7

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

进一步假设您有 Foo 类的两个实例,a并且b. 在像Java,ab可以互相调用的语言中private methods。在Ruby中,您需要使用 a protected methodprivate这是和protected方法之间的主要区别Ruby

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

于 2016-03-30T14:05:59.140 回答
6

查看“ Ruby Programming/Syntax/Classes ”以获得详细的示例和解释。

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

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

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

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

于 2012-03-27T03:06:25.613 回答
5

区别在于Visibility以及它们如何受Inheritance影响:

能见度

|| 任何地方|| Public 可以从类的内部和外部访问。

|| 课堂内|| Private 和 Protected 都只能从类内部访问。

Protected 和 Private 之间的相似之处:

  • 两者都可以通过公共方法从类外部访问。

受保护和私有之间的区别是:

  • 不能用接收器调用私有方法(甚至不能用#self)。除非...调用PRIVATE SETTER 方法。如果您尝试删除接收器,Ruby 将创建一个局部变量。在这种情况下,自我是必须的。

  • 受保护的可能会或可能不会使用自我。

  • 受保护的可以访问来自同一类的另一个对象的受保护方法,私有不能。

说到继承

  • 私有方法只能在子类上隐式调用(只是方法的名称),但不能显式调用(使用#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 
于 2017-09-01T09:35:59.660 回答
2

我认为如果您无法理解这个概念,那么分解一个显式接收器是很重要的。

显式接收者是接受消息的对象。

 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.

当一个方法是私有的时,它只能被定义在其类中的对象内部的其他方法使用。

于 2016-09-17T21:26:50.673 回答
0

研究了我从这里获取的信息,我通过错误扩展了解释,并且在我看来,这有助于理解为什么以及如何使用受保护的而不是私有的。

1) 受保护:

第 12 行崩溃,因为接收到的参数来自另一个类,错误信息很清楚:

v.rb:12:in `==': undefined method `sku' for "Object of another class ==> crash":String (NoMethodError)

2)私人:

如果从第 8 行和第 12 行中删除self,并且我将protected更改为private,则会崩溃,因为在第 12 行中,其他人不知道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"
于 2016-05-25T10:01:24.750 回答