“私人”,“公共”和“受保护的方法”之间有什么区别?

时间:2012-03-27 02:54:30

标签: ruby access-specifier public-method

我正在学习Ruby,并且已经达到了我感到困惑的程度。

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

7 个答案:

答案 0 :(得分:37)

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

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

例如:面包师将bake方法视为公开,但break_eggs为私有

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

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

最后但并非最不重要:

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

如果“D类< C”,则D将表现出与C

的实例相同的访问行为

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

答案 1 :(得分:31)

public方法向所有人开放。至于privateprotected,我指的是“Ruby Private Methods vs. Protected Methods”:

  

“私人”和“受保护”方法之间的区别是什么?   红宝石?在Ruby中,'私有'和'私有'之间的主要区别   'protected'方法是一个私有方法无法调用   显式接收器,而受保护的方法可以。什么是   “明确的接收者”,你问?显式接收器是对象   正在收到一条消息。在以下示例中,我们有一个接收器   ('parent')和方法('get_name')。 '父'对象是   接收执行'get_name'方法的指令。

答案 2 :(得分:6)

查看“Ruby Programming/Syntax/Classes”以获取详细示例和说明。

简单地说,privatepublicprotected方法之间的差异是程序中该方法的可见性,有点像只读,读取和写入,而且几乎看不见

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

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

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

答案 3 :(得分:5)

让我解释一下 Privateprotected方法在Ruby中的工作方式略有不同 编程语言。假设您有一个名为Foo的类和一个子类SubFoo。 在像Java这样的语言中,SubFoo无法访问Foo定义的任何私有方法。 正如解决方案中所见,Ruby没有办法隐藏类的方法。 类。通过这种方式,Ruby的私有作品就像Java的{​​{1}}一样。

进一步假设您有两个Foo类实例,protecteda。在语言中 例如bJavaa可以互相调用b。在private methods中,您需要使用 Ruby为此。这是protected methodprivateprotected方法之间的主要区别。

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" 的博客,了解更清晰的图片http://tenderlovemaking.com/2012/09/07/protected-methods-and-ruby-2-0.html

答案 4 :(得分:5)

区别在于可见性以及继承对它们的影响:

可见性

|| 任何地方 ||可以从班级内外访问公共。

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

受保护和私有之间的相似性

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

受保护和私有之间的差异是:

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

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

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

谈到继承

  • 私有方法只能隐式调用子类(只是方法名称)但不明确(使用#self)。

  • 可以双向调用受保护的方式(隐式或显式地使用或不使用#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 

答案 5 :(得分:1)

如果您在掌握这个概念时遇到困难,我认为打破一个明确的接收器是非常重要的。

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

 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.

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

答案 6 :(得分:0)

研究我从here获取的信息,我通过错误扩展了解释,并且根据我的观点,有助于理解为什么以及如何使用受保护而非私有。

1)受保护:

第num 12行崩溃,因为收到的参数来自另一个类,错误信息是明确的:

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

2)私人:

如果从第8行和第12行删除 self ,并且我为私有更改受保护的,则崩溃,因为在第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"