Skip to content

Ruby 面向对象

面向对象编程(OOP)是Ruby的核心特性之一。在Ruby中,一切都是对象,这使得面向对象编程变得非常自然和强大。Ruby提供了丰富的面向对象特性,包括类、对象、继承、模块、封装和多态等。本章将详细介绍Ruby中面向对象编程的各种概念和最佳实践。

🎯 面向对象基础

什么是面向对象编程

面向对象编程是一种编程范式,它使用"对象"来设计软件。对象是数据和操作数据的方法的组合。Ruby中的面向对象特性包括:

  • 类(Class):对象的模板或蓝图
  • 对象(Object):类的实例
  • 封装(Encapsulation):隐藏内部实现细节
  • 继承(Inheritance):从现有类创建新类
  • 多态(Polymorphism):同一接口的不同实现
  • 模块(Module):代码重用和命名空间
ruby
# 基本类定义
class Person
  # 构造方法
  def initialize(name, age)
    @name = name  # 实例变量
    @age = age
  end
  
  # 实例方法
  def introduce
    "我是#{@name},今年#{@age}岁"
  end
  
  # getter方法
  def name
    @name
  end
  
  # setter方法
  def name=(new_name)
    @name = new_name
  end
end

# 创建对象
person = Person.new("张三", 25)
puts person.introduce  # 我是张三,今年25岁

# 使用getter和setter
puts person.name       # 张三
person.name = "李四"
puts person.name       # 李四

类和对象基础

ruby
# 类定义
class Car
  # 类变量
  @@total_cars = 0
  
  # 构造方法
  def initialize(brand, model)
    @brand = brand
    @model = model
    @mileage = 0
    @@total_cars += 1
  end
  
  # 实例方法
  def drive(distance)
    @mileage += distance
    "行驶了#{distance}公里,总里程#{@mileage}公里"
  end
  
  # 类方法
  def self.total_cars
    @@total_cars
  end
  
  # 实例变量访问器
  attr_reader :brand, :model, :mileage
  attr_writer :mileage
  attr_accessor :color  # 自动生成getter和setter
end

# 创建对象
car1 = Car.new("丰田", "卡罗拉")
car2 = Car.new("本田", "雅阁")

# 使用对象
puts car1.brand        # 丰田
puts car1.drive(100)   # 行驶了100公里,总里程100公里
car1.color = "红色"
puts car1.color        # 红色

# 调用类方法
puts Car.total_cars    # 2

🏗️ 类的定义和方法

构造方法和初始化

ruby
class Student
  # 使用attr_accessor自动生成访问器
  attr_accessor :name, :age, :grade
  
  # 构造方法
  def initialize(name, age, grade = "未知")
    @name = name
    @age = age
    @grade = grade
    @courses = []  # 默认值
  end
  
  # 带默认参数的方法
  def enroll(course, semester = "秋季")
    @courses << { name: course, semester: semester }
  end
  
  # 带可变参数的方法
  def add_grades(*grades)
    @grades = grades.flatten
  end
  
  # 带关键字参数的方法
  def update_info(name: nil, age: nil, grade: nil)
    @name = name if name
    @age = age if age
    @grade = grade if grade
  end
  
  # 带块参数的方法
  def with_logging
    puts "开始操作"
    result = yield if block_given?
    puts "操作完成"
    result
  end
  
  # 实例方法
  def info
    "姓名: #{@name}, 年龄: #{@age}, 年级: #{@grade}"
  end
  
  def courses
    @courses.map { |course| "#{course[:name]} (#{course[:semester]})" }
  end
end

# 使用Student类
student = Student.new("张三", 20, "大二")
student.enroll("数学")
student.enroll("英语", "春季")
student.add_grades(85, 92, 78)

puts student.info
puts student.courses.inspect

student.update_info(age: 21, grade: "大三")
puts student.info

student.with_logging { puts "更新学生信息" }

访问控制

ruby
class BankAccount
  # 公共方法
  def initialize(account_number, initial_balance = 0)
    @account_number = account_number
    @balance = initial_balance
    @transaction_history = []
  end
  
  # 公共方法 - 任何人都可以调用
  def account_number
    @account_number
  end
  
  def balance
    @balance
  end
  
  def deposit(amount)
    return false if amount <= 0
    @balance += amount
    log_transaction("存款", amount)
    true
  end
  
  def withdraw(amount)
    return false if amount <= 0 || amount > @balance
    @balance -= amount
    log_transaction("取款", -amount)
    true
  end
  
  # 受保护方法 - 只有类及其子类可以调用
  protected
  
  def log_transaction(type, amount)
    transaction = {
      type: type,
      amount: amount,
      balance: @balance,
      timestamp: Time.now
    }
    @transaction_history << transaction
  end
  
  # 私有方法 - 只有类内部可以调用
  private
  
  def validate_amount(amount)
    amount > 0 && amount.is_a?(Numeric)
  end
  
  def generate_statement
    "账户: #{@account_number}, 余额: #{@balance}"
  end
  
  # 私有方法也可以被公共方法调用
  public
  
  def print_statement
    generate_statement  # 可以调用私有方法
  end
end

# 使用银行账户
account = BankAccount.new("123456789", 1000)
puts account.account_number  # 123456789
puts account.balance         # 1000

account.deposit(500)
puts account.balance         # 1500

account.withdraw(200)
puts account.balance         # 1300

puts account.print_statement # 账户: 123456789, 余额: 1300

# account.log_transaction("测试", 100)  # 错误:受保护方法
# account.generate_statement            # 错误:私有方法

🔗 继承和多态

类继承

ruby
# 基类
class Animal
  attr_accessor :name, :age
  
  def initialize(name, age)
    @name = name
    @age = age
  end
  
  # 虚方法(子类应该重写)
  def speak
    raise NotImplementedError, "子类必须实现speak方法"
  end
  
  # 公共方法
  def info
    "#{@name}是一只#{@age}岁的动物"
  end
  
  # 私有方法
  private
  
  def species
    "动物"
  end
end

# 继承基类
class Dog < Animal
  attr_accessor :breed
  
  def initialize(name, age, breed)
    super(name, age)  # 调用父类构造方法
    @breed = breed
  end
  
  # 重写父类方法
  def speak
    "#{@name}汪汪叫"
  end
  
  # 新增方法
  def fetch
    "#{@name}去捡球"
  end
  
  # 重写父类方法并调用父类方法
  def info
    super + ",品种是#{@breed}"
  end
end

class Cat < Animal
  attr_accessor :color
  
  def initialize(name, age, color)
    super(name, age)
    @color = color
  end
  
  # 重写父类方法
  def speak
    "#{@name}喵喵叫"
  end
  
  # 新增方法
  def climb
    "#{@name}爬树"
  end
end

# 使用继承
dog = Dog.new("旺财", 3, "金毛")
cat = Cat.new("咪咪", 2, "橘色")

puts dog.info        # 旺财是一只3岁的动物,品种是金毛
puts dog.speak       # 旺财汪汪叫
puts dog.fetch       # 旺财去捡球

puts cat.info        # 咪咪是一只2岁的动物
puts cat.speak       # 咪咪喵喵叫
puts cat.climb       # 咪咪爬树

方法查找和super关键字

ruby
class A
  def method1
    "A#method1"
  end
  
  def method2
    "A#method2"
  end
end

class B < A
  def method1
    "B#method1 (#{super})"  # 调用父类方法
  end
  
  def method2
    super  # 直接调用父类方法
  end
  
  def method3
    "B#method3"
  end
end

class C < B
  def method1
    "C#method1 (#{super})"  # 调用B#method1,B又调用A#method1
  end
end

# 方法查找链
a = A.new
b = B.new
c = C.new

puts a.method1  # A#method1
puts b.method1  # B#method1 (A#method1)
puts c.method1  # C#method1 (B#method1 (A#method1))

puts a.method2  # A#method2
puts b.method2  # A#method2
puts c.method2  # A#method2

puts b.method3  # B#method3
puts c.method3  # B#method3

📦 模块和混入

模块定义和使用

ruby
# 定义模块
module Drawable
  def draw
    "绘制图形"
  end
  
  def erase
    "擦除图形"
  end
  
  # 模块常量
  PI = 3.14159
end

module Movable
  def move(x, y)
    "移动到坐标(#{x}, #{y})"
  end
  
  def rotate(angle)
    "旋转#{angle}度"
  end
end

# 使用模块(包含)
class Shape
  include Drawable
  include Movable
  
  attr_accessor :x, :y
  
  def initialize(x = 0, y = 0)
    @x, @y = x, y
  end
  
  def position
    "位置: (#{@x}, #{@y})"
  end
end

# 使用扩展模块(extend)
class Circle < Shape
  extend Drawable  # 作为类方法扩展
  
  attr_accessor :radius
  
  def initialize(x, y, radius)
    super(x, y)
    @radius = radius
  end
  
  def area
    Math::PI * @radius ** 2
  end
  
  # 类方法(通过extend获得)
  def self.draw_circle
    "绘制圆形"
  end
end

# 使用模块
shape = Shape.new(10, 20)
puts shape.draw           # 绘制图形
puts shape.move(30, 40)   # 移动到坐标(30, 40)
puts shape.position       # 位置: (30, 40)

circle = Circle.new(0, 0, 5)
puts circle.area          # 78.53981633974483
puts circle.position      # 位置: (0, 0)

# 调用类方法
puts Circle.draw          # 绘制图形(来自Drawable模块)
puts Circle.draw_circle   # 绘制圆形

模块混入和命名空间

ruby
# 命名空间模块
module Graphics
  class Point
    attr_accessor :x, :y
    
    def initialize(x, y)
      @x, @y = x, y
    end
    
    def distance(other)
      Math.sqrt((@x - other.x) ** 2 + (@y - other.y) ** 2)
    end
  end
  
  class Line
    attr_accessor :start_point, :end_point
    
    def initialize(start_point, end_point)
      @start_point = start_point
      @end_point = end_point
    end
    
    def length
      @start_point.distance(@end_point)
    end
  end
end

# 使用命名空间
point1 = Graphics::Point.new(0, 0)
point2 = Graphics::Point.new(3, 4)
line = Graphics::Line.new(point1, point2)

puts point1.distance(point2)  # 5.0
puts line.length              # 5.0

# 混入模块提供共享功能
module ComparableByAge
  def <=>(other)
    @age <=> other.age
  end
  
  def >(other)
    (@age > other.age)
  end
  
  def <(other)
    (@age < other.age)
  end
  
  def ==(other)
    @age == other.age
  end
end

class Person
  include Comparable
  include ComparableByAge
  
  attr_accessor :name, :age
  
  def initialize(name, age)
    @name, @age = name, age
  end
  
  def to_s
    "#{@name}(#{@age}岁)"
  end
end

# 使用比较功能
people = [
  Person.new("张三", 25),
  Person.new("李四", 30),
  Person.new("王五", 20)
]

puts people.sort.map(&:to_s)  # 王五(20岁), 张三(25岁), 李四(30岁)
puts people.max.to_s          # 李四(30岁)
puts people.min.to_s          # 王五(20岁)

🎯 面向对象实践示例

用户管理系统

ruby
# 基础用户类
class User
  attr_accessor :username, :email, :created_at
  attr_reader :id
  
  @@next_id = 1
  @@users = {}
  
  def initialize(username, email)
    @id = @@next_id
    @@next_id += 1
    @username = username
    @email = email
    @created_at = Time.now
    @active = true
    
    @@users[@id] = self
  end
  
  def activate
    @active = true
  end
  
  def deactivate
    @active = false
  end
  
  def active?
    @active
  end
  
  def info
    "用户ID: #{@id}, 用户名: #{@username}, 邮箱: #{@email}, 状态: #{@active ? '活跃' : '非活跃'}"
  end
  
  # 类方法
  def self.find(id)
    @@users[id]
  end
  
  def self.all
    @@users.values
  end
  
  def self.active_users
    @@users.values.select(&:active?)
  end
  
  def self.deactivated_users
    @@users.values.reject(&:active?)
  end
end

# 管理员用户类
class AdminUser < User
  attr_accessor :permissions
  
  def initialize(username, email, permissions = [])
    super(username, email)
    @permissions = permissions
  end
  
  def grant_permission(permission)
    @permissions << permission unless @permissions.include?(permission)
  end
  
  def revoke_permission(permission)
    @permissions.delete(permission)
  end
  
  def can?(permission)
    @permissions.include?(permission)
  end
  
  # 重写info方法
  def info
    super + ", 权限: #{@permissions.join(', ')}"
  end
  
  # 管理员特有方法
  def deactivate_user(user_id)
    user = User.find(user_id)
    user&.deactivate
  end
  
  def list_all_users
    User.all.map(&:info)
  end
end

# 使用用户管理系统
# 创建普通用户
user1 = User.new("zhangsan", "zhangsan@example.com")
user2 = User.new("lisi", "lisi@example.com")

# 创建管理员用户
admin = AdminUser.new("admin", "admin@example.com", ["manage_users", "view_reports"])

# 管理员操作
admin.grant_permission("delete_users")
puts admin.info

# 停用用户
admin.deactivate_user(user2.id)
puts user2.active?  # false

# 查看所有用户
puts "所有用户:"
User.all.each { |user| puts user.info }

puts "活跃用户数: #{User.active_users.length}"
puts "非活跃用户数: #{User.deactivated_users.length}"

银行系统

ruby
# 银行账户基类
class BankAccount
  attr_reader :account_number, :balance, :owner
  
  @@next_account_number = 100000
  @@accounts = {}
  
  def initialize(owner, initial_balance = 0)
    @account_number = @@next_account_number
    @@next_account_number += 1
    @owner = owner
    @balance = initial_balance
    @transactions = []
    
    @@accounts[@account_number] = self
    log_transaction("开户", initial_balance)
  end
  
  def deposit(amount)
    return false if amount <= 0
    @balance += amount
    log_transaction("存款", amount)
    true
  end
  
  def withdraw(amount)
    return false if amount <= 0 || amount > @balance
    @balance -= amount
    log_transaction("取款", -amount)
    true
  end
  
  def transfer_to(other_account, amount)
    return false if amount <= 0 || amount > @balance
    return false unless other_account.is_a?(BankAccount)
    
    withdraw(amount)
    other_account.deposit(amount)
    log_transaction("转账到#{other_account.account_number}", -amount)
    other_account.log_transaction("从#{@account_number}转账", amount)
    true
  end
  
  def transaction_history
    @transactions.dup
  end
  
  def self.find(account_number)
    @@accounts[account_number]
  end
  
  def self.all_accounts
    @@accounts.values
  end
  
  def self.total_balance
    @@accounts.values.sum(&:balance)
  end
  
  protected
  
  def log_transaction(type, amount)
    transaction = {
      type: type,
      amount: amount,
      balance: @balance,
      timestamp: Time.now
    }
    @transactions << transaction
  end
end

# 储蓄账户
class SavingsAccount < BankAccount
  def initialize(owner, initial_balance = 0, interest_rate = 0.02)
    super(owner, initial_balance)
    @interest_rate = interest_rate
    @last_interest_date = Date.today
  end
  
  def add_interest
    today = Date.today
    return if today <= @last_interest_date
    
    interest = @balance * @interest_rate
    deposit(interest)
    log_transaction("利息", interest)
    @last_interest_date = today
  end
  
  def info
    "储蓄账户 #{@account_number}, 余额: #{@balance}, 利率: #{@interest_rate * 100}%"
  end
end

# 支票账户
class CheckingAccount < BankAccount
  def initialize(owner, initial_balance = 0, overdraft_limit = 0)
    super(owner, initial_balance)
    @overdraft_limit = overdraft_limit
  end
  
  # 重写取款方法以支持透支
  def withdraw(amount)
    return false if amount <= 0
    return false if (@balance + @overdraft_limit) < amount
    
    @balance -= amount
    log_transaction("取款", -amount)
    true
  end
  
  def info
    "支票账户 #{@account_number}, 余额: #{@balance}, 透支额度: #{@overdraft_limit}"
  end
end

# 银行管理系统
class Bank
  def initialize(name)
    @name = name
    @accounts = []
  end
  
  def open_savings_account(owner, initial_balance = 0, interest_rate = 0.02)
    account = SavingsAccount.new(owner, initial_balance, interest_rate)
    @accounts << account
    account
  end
  
  def open_checking_account(owner, initial_balance = 0, overdraft_limit = 0)
    account = CheckingAccount.new(owner, initial_balance, overdraft_limit)
    @accounts << account
    account
  end
  
  def find_account(account_number)
    @accounts.find { |account| account.account_number == account_number }
  end
  
  def total_assets
    @accounts.sum(&:balance)
  end
  
  def accounts_info
    @accounts.map(&:info)
  end
end

# 使用银行系统
bank = Bank.new("中国银行")

# 开设账户
savings = bank.open_savings_account("张三", 10000, 0.03)
checking = bank.open_checking_account("李四", 5000, 1000)

# 操作账户
savings.deposit(2000)
checking.withdraw(6000)  # 使用透支额度

# 转账
savings.transfer_to(checking, 3000)

# 查看账户信息
puts savings.info
puts checking.info

puts "银行总资产: #{bank.total_assets}"

# 查看交易历史
puts "储蓄账户交易历史:"
savings.transaction_history.each do |transaction|
  puts "  #{transaction[:timestamp].strftime('%Y-%m-%d %H:%M')} - #{transaction[:type]}: #{transaction[:amount]}, 余额: #{transaction[:balance]}"
end

📊 面向对象设计原则

SOLID原则应用

ruby
# S - 单一职责原则 (Single Responsibility Principle)
# 每个类应该只有一个改变的理由

# 不好的设计
class User
  def initialize(name, email)
    @name = name
    @email = email
  end
  
  # 用户数据管理
  def save
    # 保存到数据库
  end
  
  def validate
    # 验证用户数据
  end
  
  # 邮件发送
  def send_welcome_email
    # 发送欢迎邮件
  end
  
  # 日志记录
  def log_activity(activity)
    # 记录用户活动
  end
end

# 好的设计
class User
  attr_accessor :name, :email
  
  def initialize(name, email)
    @name = name
    @email = email
  end
end

class UserDatabase
  def self.save(user)
    # 保存用户到数据库
  end
  
  def self.find(id)
    # 从数据库查找用户
  end
end

class UserValidator
  def self.validate(user)
    # 验证用户数据
  end
end

class EmailService
  def self.send_welcome_email(user)
    # 发送欢迎邮件
  end
end

class ActivityLogger
  def self.log(user, activity)
    # 记录用户活动
  end
end

# O - 开放-封闭原则 (Open/Closed Principle)
# 对扩展开放,对修改封闭

# 基础报表类
class Report
  def generate
    data = fetch_data
    format_data(data)
  end
  
  private
  
  def fetch_data
    # 获取数据的通用逻辑
    []
  end
  
  def format_data(data)
    # 默认格式化
    data.join("\n")
  end
end

# 扩展报表类而不修改原有代码
class PDFReport < Report
  def format_data(data)
    # PDF格式化
    "PDF: #{data.join(', ')}"
  end
end

class ExcelReport < Report
  def format_data(data)
    # Excel格式化
    "Excel: #{data.join("\t")}"
  end
end

# L - 里氏替换原则 (Liskov Substitution Principle)
# 子类应该能够替换父类

class Bird
  def fly
    "鸟在飞"
  end
end

class Sparrow < Bird
  def fly
    "麻雀在飞"
  end
end

class Ostrich < Bird
  # 鸵鸟不会飞,违反了里氏替换原则
  def fly
    raise "鸵鸟不会飞"
  end
end

# 改进设计
class Bird
  # 鸟类的基础功能
end

class FlyingBird < Bird
  def fly
    "鸟在飞"
  end
end

class Sparrow < FlyingBird
  def fly
    "麻雀在飞"
  end
end

class Ostrich < Bird
  def run
    "鸵鸟在跑"
  end
end

# I - 接口隔离原则 (Interface Segregation Principle)
# 客户端不应该依赖它不需要的接口

# 不好的设计
module Worker
  def work
    # 工作
  end
  
  def eat
    # 吃饭
  end
  
  def sleep
    # 睡觉
  end
end

class HumanWorker
  include Worker
  
  def work
    "人类在工作"
  end
  
  def eat
    "人类在吃饭"
  end
  
  def sleep
    "人类在睡觉"
  end
end

class RobotWorker
  include Worker
  
  def work
    "机器人在工作"
  end
  
  def eat
    # 机器人不需要吃饭
    raise "机器人不需要吃饭"
  end
  
  def sleep
    # 机器人不需要睡觉
    raise "机器人不需要睡觉"
  end
end

# 好的设计
module Workable
  def work
    # 工作
  end
end

module Eatable
  def eat
    # 吃饭
  end
end

module Sleepable
  def sleep
    # 睡觉
  end
end

class HumanWorker
  include Workable
  include Eatable
  include Sleepable
  
  def work
    "人类在工作"
  end
  
  def eat
    "人类在吃饭"
  end
  
  def sleep
    "人类在睡觉"
  end
end

class RobotWorker
  include Workable
  
  def work
    "机器人在工作"
  end
end

# D - 依赖倒置原则 (Dependency Inversion Principle)
# 依赖于抽象,而不是具体实现

# 不好的设计
class EmailNotifier
  def notify(message)
    # 发送邮件通知
    puts "发送邮件: #{message}"
  end
end

class UserService
  def initialize
    @notifier = EmailNotifier.new
  end
  
  def create_user(user_data)
    # 创建用户逻辑
    @notifier.notify("用户已创建")
  end
end

# 好的设计
class Notifier
  def notify(message)
    raise NotImplementedError
  end
end

class EmailNotifier < Notifier
  def notify(message)
    puts "发送邮件: #{message}"
  end
end

class SMSNotifier < Notifier
  def notify(message)
    puts "发送短信: #{message}"
  end
end

class UserService
  def initialize(notifier)
    @notifier = notifier
  end
  
  def create_user(user_data)
    # 创建用户逻辑
    @notifier.notify("用户已创建")
  end
end

# 使用
email_notifier = EmailNotifier.new
sms_notifier = SMSNotifier.new

user_service1 = UserService.new(email_notifier)
user_service2 = UserService.new(sms_notifier)

🛡️ 面向对象最佳实践

1. 设计模式应用

ruby
# 单例模式
class Logger
  @@instance = nil
  
  private_class_method :new
  
  def self.instance
    @@instance ||= new
  end
  
  def log(message)
    puts "[#{Time.now}] #{message}"
  end
  
  private
  
  def initialize
    # 私有构造方法
  end
end

# 使用单例
logger1 = Logger.instance
logger2 = Logger.instance
puts logger1.equal?(logger2)  # true

logger1.log("第一条日志")
logger2.log("第二条日志")

# 工厂模式
class AnimalFactory
  def self.create_animal(type, name)
    case type.downcase
    when 'dog'
      Dog.new(name)
    when 'cat'
      Cat.new(name)
    when 'bird'
      Bird.new(name)
    else
      raise "未知的动物类型: #{type}"
    end
  end
end

# 使用工厂
dog = AnimalFactory.create_animal('dog', '旺财')
cat = AnimalFactory.create_animal('cat', '咪咪')

# 观察者模式
class Subject
  def initialize
    @observers = []
  end
  
  def add_observer(observer)
    @observers << observer
  end
  
  def remove_observer(observer)
    @observers.delete(observer)
  end
  
  def notify_observers
    @observers.each { |observer| observer.update(self) }
  end
end

class TemperatureSensor < Subject
  attr_reader :temperature
  
  def initialize
    super
    @temperature = 0
  end
  
  def temperature=(temp)
    @temperature = temp
    notify_observers if temp > 30
  end
end

class TemperatureDisplay
  def update(subject)
    puts "警告: 温度过高! 当前温度: #{subject.temperature}°C"
  end
end

class TemperatureLogger
  def update(subject)
    puts "记录温度: #{subject.temperature}°C at #{Time.now}"
  end
end

# 使用观察者模式
sensor = TemperatureSensor.new
display = TemperatureDisplay.new
logger = TemperatureLogger.new

sensor.add_observer(display)
sensor.add_observer(logger)

sensor.temperature = 25  # 无警告
sensor.temperature = 35  # 触发警告

2. 代码组织和结构

ruby
# 模块化设计
module Payment
  class Base
    def initialize(amount)
      @amount = amount
    end
    
    def process
      raise NotImplementedError, "子类必须实现process方法"
    end
  end
  
  class CreditCard < Base
    def initialize(amount, card_number, cvv)
      super(amount)
      @card_number = card_number
      @cvv = cvv
    end
    
    def process
      "处理信用卡支付: #{@amount}元"
    end
  end
  
  class Alipay < Base
    def initialize(amount, account)
      super(amount)
      @account = account
    end
    
    def process
      "处理支付宝支付: #{@amount}元"
    end
  end
  
  class WeChatPay < Base
    def initialize(amount, openid)
      super(amount)
      @openid = openid
    end
    
    def process
      "处理微信支付: #{@amount}元"
    end
  end
end

# 使用支付模块
credit_card = Payment::CreditCard.new(100, "1234****5678", "123")
alipay = Payment::Alipay.new(100, "user@example.com")
wechat = Payment::WeChatPay.new(100, "openid123")

puts credit_card.process
puts alipay.process
puts wechat.process

# 策略模式
class PaymentProcessor
  def initialize(payment_strategy)
    @payment_strategy = payment_strategy
  end
  
  def process_payment(amount)
    @payment_strategy.process(amount)
  end
end

# 使用策略模式
processor1 = PaymentProcessor.new(Payment::CreditCard.new(100, "1234****5678", "123"))
processor2 = PaymentProcessor.new(Payment::Alipay.new(100, "user@example.com"))

puts processor1.process_payment(100)
puts processor2.process_payment(100)

3. 测试友好的设计

ruby
# 依赖注入提高可测试性
class OrderService
  def initialize(payment_gateway = nil, inventory_service = nil)
    @payment_gateway = payment_gateway || PaymentGateway.new
    @inventory_service = inventory_service || InventoryService.new
  end
  
  def process_order(order)
    # 检查库存
    return false unless @inventory_service.check_stock(order.items)
    
    # 处理支付
    payment_result = @payment_gateway.charge(order.total_amount)
    return false unless payment_result.success?
    
    # 更新库存
    @inventory_service.update_stock(order.items)
    
    true
  end
end

# 模拟对象用于测试
class MockPaymentGateway
  def charge(amount)
    OpenStruct.new(success?: true)
  end
end

class MockInventoryService
  def check_stock(items)
    true
  end
  
  def update_stock(items)
    # 模拟更新库存
  end
end

# 测试代码
# order_service = OrderService.new(MockPaymentGateway.new, MockInventoryService.new)
# result = order_service.process_order(order)
# assert(result, "订单处理应该成功")

📚 下一步学习

掌握了Ruby面向对象编程后,建议继续学习:

继续您的Ruby学习之旅吧!

本站内容仅供学习和研究使用。