Ruby多态 #
一、多态概述 #
多态是指同一操作作用于不同对象时产生不同行为。Ruby通过鸭子类型实现多态。
二、鸭子类型 #
2.1 基本概念 #
“如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子。”
ruby
class Duck
def quack
"Quack!"
end
end
class Person
def quack
"I'm pretending to be a duck!"
end
end
def make_it_quack(duck)
duck.quack
end
make_it_quack(Duck.new)
make_it_quack(Person.new)
2.2 类型检查 vs 鸭子类型 #
ruby
def process_wrong(obj)
raise TypeError unless obj.is_a?(String)
obj.upcase
end
def process_right(obj)
obj.upcase
end
process_right("hello")
process_right(:hello)
2.3 respond_to? #
ruby
def safe_quack(obj)
if obj.respond_to?(:quack)
obj.quack
else
"Cannot quack"
end
end
三、方法重写多态 #
3.1 基本用法 #
ruby
class Animal
def speak
"Some sound"
end
end
class Dog < Animal
def speak
"Woof!"
end
end
class Cat < Animal
def speak
"Meow!"
end
end
def make_sound(animal)
animal.speak
end
make_sound(Dog.new)
make_sound(Cat.new)
3.2 数组多态 #
ruby
animals = [Dog.new, Cat.new, Animal.new]
animals.map(&:speak)
四、接口模式 #
4.1 模块接口 #
ruby
module Drawable
def draw
raise NotImplementedError
end
end
class Circle
include Drawable
def draw
"Drawing circle"
end
end
class Square
include Drawable
def draw
"Drawing square"
end
end
def render(drawable)
drawable.draw
end
4.2 抽象基类 #
ruby
class Shape
def area
raise NotImplementedError
end
def perimeter
raise NotImplementedError
end
end
class Rectangle < Shape
def initialize(width, height)
@width = width
@height = height
end
def area
@width * @height
end
def perimeter
2 * (@width + @height)
end
end
五、策略模式 #
5.1 基本实现 #
ruby
class PaymentProcessor
def initialize(strategy)
@strategy = strategy
end
def process(amount)
@strategy.pay(amount)
end
end
class CreditCardPayment
def pay(amount)
"Paid #{amount} via Credit Card"
end
end
class PayPalPayment
def pay(amount)
"Paid #{amount} via PayPal"
end
end
processor = PaymentProcessor.new(CreditCardPayment.new)
processor.process(100)
processor = PaymentProcessor.new(PayPalPayment.new)
processor.process(100)
5.2 使用Lambda #
ruby
class Calculator
STRATEGIES = {
add: ->(a, b) { a + b },
subtract: ->(a, b) { a - b },
multiply: ->(a, b) { a * b }
}
def calculate(operation, a, b)
STRATEGIES[operation].call(a, b)
end
end
calc = Calculator.new
calc.calculate(:add, 5, 3)
calc.calculate(:multiply, 5, 3)
六、实用示例 #
6.1 文件处理器 #
ruby
class FileHandler
def initialize(parser)
@parser = parser
end
def process(file)
data = read(file)
@parser.parse(data)
end
private
def read(file)
File.read(file)
end
end
class JSONParser
def parse(data)
JSON.parse(data)
end
end
class XMLParser
def parse(data)
Nokogiri::XML(data)
end
end
class CSVParser
def parse(data)
CSV.parse(data)
end
end
6.2 通知系统 #
ruby
class Notifier
def initialize(channels)
@channels = channels
end
def notify(message)
@channels.each { |channel| channel.send(message) }
end
end
class EmailChannel
def send(message)
puts "Email: #{message}"
end
end
class SMSChannel
def send(message)
puts "SMS: #{message}"
end
end
class PushChannel
def send(message)
puts "Push: #{message}"
end
end
notifier = Notifier.new([EmailChannel.new, SMSChannel.new, PushChannel.new])
notifier.notify("Hello!")
6.3 排序策略 #
ruby
class Sorter
def initialize(strategy)
@strategy = strategy
end
def sort(items)
items.sort(&@strategy)
end
end
by_name = Sorter.new(->(a, b) { a[:name] <=> b[:name] })
by_age = Sorter.new(->(a, b) { a[:age] <=> b[:age] })
people = [
{ name: "Bob", age: 30 },
{ name: "Alice", age: 25 },
{ name: "Charlie", age: 35 }
]
by_name.sort(people)
by_age.sort(people)
6.4 数据导出 #
ruby
class DataExporter
def initialize(formatter)
@formatter = formatter
end
def export(data)
@formatter.format(data)
end
end
class JSONFormatter
def format(data)
JSON.generate(data)
end
end
class CSVFormatter
def format(data)
data.map(&:to_csv).join("\n")
end
end
class XMLFormatter
def format(data)
data.to_xml
end
end
七、多态最佳实践 #
7.1 依赖接口而非实现 #
ruby
def process_wrong(obj)
raise TypeError unless obj.is_a?(MyClass)
obj.do_something
end
def process_right(obj)
obj.do_something
end
7.2 使用respond_to?检查 #
ruby
def safe_process(obj)
if obj.respond_to?(:required_method)
obj.required_method
else
handle_missing_method(obj)
end
end
7.3 小对象组合 #
ruby
class ReportGenerator
def initialize(formatter, exporter)
@formatter = formatter
@exporter = exporter
end
def generate(data)
formatted = @formatter.format(data)
@exporter.export(formatted)
end
end
八、总结 #
本章我们学习了:
- 鸭子类型:基于行为而非类型
- 方法重写:子类多态
- 接口模式:模块接口、抽象基类
- 策略模式:运行时切换行为
- 实用示例:文件处理、通知系统、数据导出
- 最佳实践:依赖接口、使用respond_to?、组合对象
接下来让我们学习Ruby的特殊方法!
最后更新:2026-03-27