ZetCode

Ruby 私有方法

最后修改日期:2025 年 4 月 27 日

本教程解释了如何使用 Ruby 的 private 方法修饰符。私有方法是 Ruby 面向对象编程的重要组成部分。

private 关键字使方法只能在类内部访问。它们不能通过显式接收者调用,只能调用当前对象(self)。

私有方法通过隐藏实现细节来强制封装。它们有助于创建清晰的接口并防止滥用类内部的功能。

基本私有方法示例

这个简单的例子演示了 Ruby 中私有方法的基本用法。私有方法只能在类定义内部调用。

basic_private.rb
class Person
  def greet
    puts "Hello, #{name}"
  end

  private
  
  def name
    "John Doe"
  end
end

person = Person.new
person.greet
# person.name # This would raise NoMethodError

name 方法是私有的,只能在内部调用。尝试在实例上直接调用它会引发 NoMethodError。

私有方法调用约定

私有方法只能在没有显式接收者的情况下调用。它们必须在隐式的 self 上调用,或者从其他方法内部调用。

private_convention.rb
class Calculator
  def add(a, b)
    validate(a)
    validate(b)
    a + b
  end

  private
  
  def validate(num)
    raise "Not a number" unless num.is_a?(Numeric)
  end
end

calc = Calculator.new
puts calc.add(5, 3)
# calc.validate(5) # This would raise NoMethodError

validate 方法是私有的,由 add 在内部使用。不能在 Calculator 实例上直接调用它。

私有类方法

要使类方法私有,我们需要使用 private_class_method 方法或在 class << self 块内定义它们。

private_class.rb
class Logger
  def self.log(message)
    format_message(message)
  end

  private_class_method def self.format_message(msg)
    "[#{Time.now}] #{msg}"
  end
end

puts Logger.log("Test message")
# Logger.format_message("Test") # This would raise NoMethodError

format_message 类方法是私有的,只能由其他类方法在内部调用。

继承中的私有方法

私有方法会被子类继承,但仍然保持私有。子类方法可以调用它们,但不能直接在实例上调用。

inheritance.rb
class Animal
  def speak
    make_sound
  end

  private
  
  def make_sound
    "Generic animal noise"
  end
end

class Dog < Animal
  def bark
    make_sound + " - Woof!"
  end
end

dog = Dog.new
puts dog.bark
# dog.make_sound # This would raise NoMethodError

Dog 类从 Animal 继承了私有的 make_sound 方法。它可以内部调用它,但不能直接暴露它。

使用 send 的私有方法

Ruby 的 send 方法可以绕过私有方法限制。这应该谨慎使用,因为它会破坏封装。

private_send.rb
class Secret
  private
  
  def hidden_method
    "Top secret information"
  end
end

secret = Secret.new
# puts secret.hidden_method # Would raise NoMethodError
puts secret.send(:hidden_method)

虽然 send 可以访问私有方法,但这通常被认为是不好的做法。它只应在测试等特殊情况下使用。

模块中的私有方法

模块可以定义私有方法,当它们被包含在类中时,这些方法会变为私有。这对于创建可重用的私有功能很有用。

module_private.rb
module Validations
  def validate_presence(value)
    raise "Cannot be blank" if value.nil? || value.empty?
  end

  private :validate_presence
end

class User
  include Validations
  
  def save(name)
    validate_presence(name)
    puts "User saved"
  end
end

user = User.new
user.save("John")
# user.validate_presence("") # This would raise NoMethodError

validate_presence 方法在模块中是私有的,并且在包含在 User 类中时保持私有。

私有设置器方法

设置器方法(以 = 结尾)必须显式设置为私有,因为默认情况下它们不能在没有接收者的情况下调用。

private_setter.rb
class BankAccount
  def initialize(balance)
    self.balance = balance
  end

  def deposit(amount)
    self.balance += amount
  end

  private
  
  attr_reader :balance
  attr_writer :balance
end

account = BankAccount.new(100)
account.deposit(50)
# account.balance = 200 # This would raise NoMethodError

balance 设置器被设为私有,同时仍然可以在类内部使用。读取器也是私有的,以完全封装 balance 属性。

来源

Ruby 可见性文档

本教程涵盖了 Ruby 的私有方法,并提供了实际示例,展示了它们在类、模块、继承和特殊情况下的用法。

作者

我的名字是 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。至今,我已撰写了 1,400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出 所有 Ruby 教程