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
九、总结 #
本章我们学习了:
- 访问控制级别:public、protected、private
- public:默认访问级别、显式声明
- private:内部实现、调用规则
- protected:类间共享、对比private
- 封装模式:最小暴露、内部隐藏、模板方法
- 最佳实践:私有方法、保护状态、共享实现
接下来让我们学习Ruby的多态!
最后更新:2026-03-27