Ruby封装 #

一、封装概述 #

封装是面向对象的核心概念之一,用于隐藏实现细节,只暴露必要的接口。

二、访问控制级别 #

级别 类内部 子类 外部
public
protected
private

三、public #

3.1 默认访问级别 #

ruby
class Person
  def greet
    "Hello!"
  end
end

person = Person.new
person.greet

3.2 显式声明 #

ruby
class Person
  public

  def greet
    "Hello!"
  end
end

3.3 方法可见性设置 #

ruby
class Person
  def greet
    "Hello!"
  end

  def farewell
    "Goodbye!"
  end

  public :greet, :farewell
end

四、private #

4.1 基本用法 #

ruby
class Person
  def initialize(name)
    @name = name
  end

  def introduce
    "Hello, I'm #{name}"
  end

  private

  def name
    @name
  end
end

person = Person.new("Ruby")
person.introduce
person.name

4.2 私有方法特点 #

ruby
class Example
  def public_method
    private_method
  end

  private

  def private_method
    "Private"
  end

  def another_private
    self.private_method
  end
end

Example.new.public_method
Example.new.another_private

4.3 Ruby 2.7+ 私有方法调用 #

ruby
class Example
  def public_method
    self.private_method
  end

  private

  def private_method
    "Private"
  end
end

Example.new.public_method

4.4 设置方法为私有 #

ruby
class Person
  def initialize(name)
    @name = name
  end

  def name
    @name
  end

  private :name
end

person = Person.new("Ruby")
person.name

五、protected #

5.1 基本用法 #

ruby
class Person
  def initialize(age)
    @age = age
  end

  def older_than?(other)
    age > other.age
  end

  protected

  def age
    @age
  end
end

alice = Person.new(30)
bob = Person.new(25)

alice.older_than?(bob)
alice.age

5.2 protected vs private #

ruby
class Person
  def initialize(age)
    @age = age
  end

  def compare_private(other)
    age > other.send(:age)
  end

  def compare_protected(other)
    age > other.age
  end

  private

  def age
    @age
  end
end

class Person
  def initialize(age)
    @age = age
  end

  def compare(other)
    age > other.age
  end

  protected

  def age
    @age
  end
end

六、访问控制模式 #

6.1 最小暴露原则 #

ruby
class User
  def initialize(email, password)
    @email = email
    @password = encrypt(password)
  end

  def authenticate(password)
    @password == encrypt(password)
  end

  private

  def encrypt(text)
    Digest::SHA256.hexdigest(text)
  end
end

6.2 内部实现隐藏 #

ruby
class Order
  def initialize(items)
    @items = items
  end

  def total
    subtotal + tax - discount
  end

  private

  def subtotal
    @items.sum(&:price)
  end

  def tax
    subtotal * 0.1
  end

  def discount
    subtotal > 100 ? subtotal * 0.05 : 0
  end
end

6.3 模板方法模式 #

ruby
class Report
  def generate
    header + content + footer
  end

  private

  def header
    "=== Report ===\n"
  end

  def footer
    "\n=== End ==="
  end

  def content
    raise NotImplementedError
  end
end

class SalesReport < Report
  private

  def content
    "Sales data..."
  end
end

七、实用示例 #

7.1 银行账户 #

ruby
class BankAccount
  def initialize(owner, initial_balance = 0)
    @owner = owner
    @balance = initial_balance
    @transactions = []
  end

  def deposit(amount)
    validate_amount(amount)
    @balance += amount
    record_transaction(:deposit, amount)
  end

  def withdraw(amount)
    validate_amount(amount)
    validate_sufficient_funds(amount)
    @balance -= amount
    record_transaction(:withdraw, amount)
  end

  def balance
    @balance
  end

  def statement
    @transactions.map { |t| format_transaction(t) }.join("\n")
  end

  private

  def validate_amount(amount)
    raise ArgumentError, "Invalid amount" if amount <= 0
  end

  def validate_sufficient_funds(amount)
    raise InsufficientFundsError if amount > @balance
  end

  def record_transaction(type, amount)
    @transactions << {
      type: type,
      amount: amount,
      balance: @balance,
      timestamp: Time.now
    }
  end

  def format_transaction(transaction)
    "[#{transaction[:timestamp]}] #{transaction[:type]}: #{transaction[:amount]}"
  end
end

7.2 配置类 #

ruby
class Configuration
  def initialize
    @settings = {}
  end

  def get(key)
    @settings[key]
  end

  def set(key, value)
    validate_key(key)
    validate_value(value)
    @settings[key] = value
  end

  def to_h
    @settings.dup
  end

  private

  def validate_key(key)
    raise ArgumentError, "Key must be a symbol" unless key.is_a?(Symbol)
  end

  def validate_value(value)
    raise ArgumentError, "Value cannot be nil" if value.nil?
  end
end

7.3 数据验证 #

ruby
class User
  attr_reader :name, :email, :age

  def initialize(name, email, age)
    @name = validate_name(name)
    @email = validate_email(email)
    @age = validate_age(age)
  end

  private

  def validate_name(name)
    raise ArgumentError, "Name cannot be empty" if name.nil? || name.empty?
    name.strip
  end

  def validate_email(email)
    raise ArgumentError, "Invalid email" unless email.match?(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i)
    email.downcase
  end

  def validate_age(age)
    raise ArgumentError, "Age must be positive" unless age.is_a?(Integer) && age > 0
    age
  end
end

八、封装最佳实践 #

8.1 使用私有方法 #

ruby
class Calculator
  def calculate(expression)
    tokens = tokenize(expression)
    validate_tokens(tokens)
    evaluate(tokens)
  end

  private

  def tokenize(expression)
    expression.split
  end

  def validate_tokens(tokens)
  end

  def evaluate(tokens)
  end
end

8.2 保护内部状态 #

ruby
class Counter
  def initialize
    @count = 0
  end

  def increment
    @count += 1
  end

  def decrement
    @count -= 1
  end

  def count
    @count
  end

  private

  attr_writer :count
end

8.3 使用protected共享实现 #

ruby
class Employee
  def initialize(salary)
    @salary = salary
  end

  def higher_paid_than?(other)
    salary > other.salary
  end

  protected

  def salary
    @salary
  end
end

九、总结 #

本章我们学习了:

  1. 访问控制级别:public、protected、private
  2. public:默认访问级别、显式声明
  3. private:内部实现、调用规则
  4. protected:类间共享、对比private
  5. 封装模式:最小暴露、内部隐藏、模板方法
  6. 最佳实践:私有方法、保护状态、共享实现

接下来让我们学习Ruby的多态!

最后更新:2026-03-27