为什么Ruby有私有和受保护的方法?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (8)

之前,我认为Ruby中的访问控制是这样工作的:

  • public- 可以被任何对象访问(例如Obj.new.public_method
  • protected - 只能从对象本身以及任何子类中访问
  • private - 与受保护的相同,但该方法不存在于子类中

然而,除了你不能用明确的接收者调用方法(即工作,但没有)之外,它看起来protectedprivate行为相同。privateself.protected_methodself.private_method

提问于
用户回答回答于

protected 方法可以由定义类或其子类的任何实例调用。

private方法只能从调用对象中调用。不能直接访问另一个实例的私有方法。

这是一个例子:

def compare_to(x)
 self.some_method <=> x.some_method
end

some_method不能在private这里。这一定是protected因为你需要它来支持显式的接收器。你典型的内部帮助方法通常可以是private因为他们永远不需要像这样调用。

值得注意的是,这与Java或C ++的工作方式不同。private在Ruby中类似于protectedJava / C ++中的子类可以访问该方法。在Ruby中,没有办法像private在Java中一样限制对子类的访问。

无论如何,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
用户回答回答于

在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>

扫码关注云+社区