Ruby 类和对象
Ruby是一种纯粹的面向对象编程语言,其中一切都是对象。本章将详细介绍Ruby中的类和对象概念,以及如何使用它们构建程序。
🎯 面向对象基础
什么是类和对象?
- 类(Class): 对象的模板或蓝图,定义了对象的属性和行为
- 对象(Object): 类的实例,具有具体的属性值和可以执行的行为
ruby
# 一切都是对象
puts 42.class # Integer
puts "Hello".class # String
puts true.class # TrueClass
puts nil.class # NilClass
# 查看对象的方法
number = 42
puts number.methods # 显示所有可用方法🏗️ 类的定义
基本类定义
ruby
# 定义一个简单的类
class Person
# 类体
end
# 创建对象(实例化)
person1 = Person.new
person2 = Person.new
puts person1.class # Person
puts person2.class # Person
puts person1.object_id # 对象ID
puts person2.object_id # 不同的对象ID构造方法 initialize
ruby
class Person
# 构造方法(初始化方法)
def initialize(name, age)
@name = name # 实例变量
@age = age
end
# 实例方法
def introduce
puts "我是#{@name},今年#{@age}岁"
end
end
# 创建对象并调用方法
person = Person.new("张三", 25)
person.introduce # 输出: 我是张三,今年25岁访问器方法
ruby
class Person
def initialize(name, age)
@name = name
@age = age
end
# getter方法
def name
@name
end
def age
@age
end
# setter方法
def name=(name)
@name = name
end
def age=(age)
@age = age
end
def introduce
puts "我是#{@name},今年#{@age}岁"
end
end
# 使用访问器方法
person = Person.new("李四", 30)
puts person.name # 李四
person.age = 31
puts person.age # 31使用attr_accessor简化访问器
ruby
class Person
# 自动生成getter和setter方法
attr_accessor :name, :age
# 等同于:
# attr_reader :name, :age # 只生成getter
# attr_writer :name, :age # 只生成setter
def initialize(name, age)
@name = name
@age = age
end
def introduce
puts "我是#{@name},今年#{@age}岁"
end
end
# 使用简化访问器
person = Person.new("王五", 28)
puts person.name # 王五
person.name = "赵六"
person.age = 29
person.introduce # 我是赵六,今年29岁📦 变量类型
实例变量
ruby
class Counter
def initialize
@count = 0 # 实例变量,以@开头
end
def increment
@count += 1
end
def count
@count
end
end
counter1 = Counter.new
counter2 = Counter.new
counter1.increment
counter1.increment
puts counter1.count # 2
puts counter2.count # 0 (不同的实例)类变量
ruby
class Counter
@@total_instances = 0 # 类变量,以@@开头
def initialize
@count = 0
@@total_instances += 1
end
def increment
@count += 1
end
def count
@count
end
# 类方法访问类变量
def self.total_instances
@@total_instances
end
end
counter1 = Counter.new
counter2 = Counter.new
counter3 = Counter.new
puts Counter.total_instances # 3全局变量
ruby
# 全局变量,以$开头(不推荐大量使用)
$global_counter = 0
class GlobalCounter
def increment
$global_counter += 1
end
def self.global_count
$global_counter
end
end
counter = GlobalCounter.new
counter.increment
counter.increment
puts GlobalCounter.global_count # 2局部变量和常量
ruby
class MathConstants
PI = 3.14159 # 常量,大写字母命名
E = 2.71828
def self.calculate_circle_area(radius)
local_variable = radius * radius # 局部变量
PI * local_variable
end
end
puts MathConstants::PI # 3.14159
puts MathConstants.calculate_circle_area(5) # 78.53975🎯 方法类型
实例方法
ruby
class Calculator
def add(a, b)
a + b
end
def subtract(a, b)
a - b
end
end
calc = Calculator.new
puts calc.add(10, 5) # 15
puts calc.subtract(10, 5) # 5类方法
ruby
class MathUtils
# 方式1: 使用self
def self.square(number)
number * number
end
# 方式2: 使用类名
def MathUtils.cube(number)
number * number * number
end
# 方式3: 在类内部定义
class << self
def power(base, exponent)
base ** exponent
end
end
end
puts MathUtils.square(4) # 16
puts MathUtils.cube(3) # 27
puts MathUtils.power(2, 3) # 8私有方法
ruby
class BankAccount
def initialize(balance)
@balance = balance
end
def deposit(amount)
if valid_amount?(amount)
@balance += amount
puts "存款成功,当前余额: #{@balance}"
else
puts "无效金额"
end
end
def withdraw(amount)
if valid_amount?(amount) && sufficient_funds?(amount)
@balance -= amount
puts "取款成功,当前余额: #{@balance}"
else
puts "取款失败"
end
end
def balance
@balance
end
private # 私有方法
def valid_amount?(amount)
amount > 0
end
def sufficient_funds?(amount)
@balance >= amount
end
end
account = BankAccount.new(1000)
account.deposit(500) # 存款成功,当前余额: 1500
account.withdraw(200) # 取款成功,当前余额: 1300
# account.valid_amount?(100) # 错误: private method受保护方法
ruby
class Animal
def initialize(name)
@name = name
end
protected # 受保护方法
def speak
"#{@name}发出声音"
end
end
class Dog < Animal
def initialize(name)
super(name)
end
def bark
speak + " 汪汪!" # 可以调用父类的受保护方法
end
end
dog = Dog.new("旺财")
puts dog.bark # 旺财发出声音 汪汪!
# dog.speak # 错误: protected method🧬 继承
基本继承
ruby
# 父类
class Vehicle
def initialize(brand, model)
@brand = brand
@model = model
end
def start_engine
puts "#{@brand} #{@model} 引擎启动"
end
def stop_engine
puts "#{@brand} #{@model} 引擎关闭"
end
def info
"#{@brand} #{@model}"
end
end
# 子类
class Car < Vehicle
def initialize(brand, model, doors)
super(brand, model) # 调用父类构造方法
@doors = doors
end
def open_trunk
puts "打开后备箱"
end
# 重写父类方法
def info
super + " (#{@doors}门)"
end
end
# 使用继承
car = Car.new("丰田", "卡罗拉", 4)
car.start_engine # 丰田 卡罗拉 引擎启动
car.open_trunk # 打开后备箱
puts car.info # 丰田 卡罗拉 (4门)方法查找链
ruby
class A
def method1
"A's method1"
end
end
class B < A
def method1
"B's method1"
end
def method2
"B's method2"
end
end
class C < B
def method1
"C's method1"
end
end
obj = C.new
puts obj.method1 # C's method1
puts obj.method2 # B's method2 (继承自B)🔄 模块和Mixin
模块定义
ruby
# 定义模块
module Flyable
def fly
"我在飞翔!"
end
def land
"我降落了!"
end
end
module Swimmable
def swim
"我在游泳!"
end
end
# 使用模块
class Bird
include Flyable # 包含模块
end
class Fish
include Swimmable
end
class Duck
include Flyable
include Swimmable
end
bird = Bird.new
puts bird.fly # 我在飞翔!
duck = Duck.new
puts duck.fly # 我在飞翔!
puts duck.swim # 我在游泳!模块作为命名空间
ruby
module MathUtils
PI = 3.14159
class Calculator
def self.add(a, b)
a + b
end
end
def self.square(number)
number * number
end
end
puts MathUtils::PI # 3.14159
puts MathUtils::Calculator.add(2, 3) # 5
puts MathUtils.square(4) # 16🎭 多态性
方法重写和多态
ruby
class Animal
def speak
"动物发出声音"
end
end
class Dog < Animal
def speak
"汪汪!"
end
end
class Cat < Animal
def speak
"喵喵!"
end
end
class Bird < Animal
def speak
"叽叽喳喳!"
end
end
# 多态性示例
animals = [Dog.new, Cat.new, Bird.new]
animals.each do |animal|
puts animal.speak # 根据对象类型调用相应方法
end
# 输出:
# 汪汪!
# 喵喵!
# 叽叽喳喳!🧱 对象生命周期
初始化和清理
ruby
class Resource
def initialize(name)
@name = name
puts "创建资源: #{@name}"
end
def use
puts "使用资源: #{@name}"
end
# 对象被垃圾回收前调用
def finalize
puts "清理资源: #{@name}"
end
# 自定义析构方法
def dispose
puts "手动清理资源: #{@name}"
end
end
# 对象生命周期
resource = Resource.new("数据库连接")
resource.use
resource.dispose # 手动清理
# resource变量超出作用域后会被垃圾回收🎯 高级特性
单例类
ruby
class MyClass
def instance_method
"实例方法"
end
class << self
def class_method
"类方法"
end
end
end
# 单例方法
obj = MyClass.new
class << obj
def singleton_method
"单例方法"
end
end
puts obj.instance_method # 实例方法
puts MyClass.class_method # 类方法
puts obj.singleton_method # 单例方法
# 检查单例类
puts obj.singleton_class
puts MyClass.singleton_class方法缺失处理
ruby
class FlexibleObject
def initialize
@data = {}
end
def method_missing(method_name, *args, &block)
if method_name.to_s.end_with?('=')
# setter方法
key = method_name.to_s.chomp('=').to_sym
@data[key] = args.first
else
# getter方法
@data[method_name]
end
end
def respond_to_missing?(method_name, include_private = false)
true
end
end
obj = FlexibleObject.new
obj.name = "张三"
obj.age = 25
puts obj.name # 张三
puts obj.age # 25🧪 实践示例
完整的银行账户系统
ruby
class BankAccount
attr_reader :account_number, :balance
attr_accessor :owner
@@total_accounts = 0
def initialize(owner, initial_balance = 0)
@owner = owner
@balance = initial_balance
@account_number = generate_account_number
@@total_accounts += 1
end
def deposit(amount)
if amount > 0
@balance += amount
log_transaction("存款", amount)
true
else
puts "存款金额必须大于0"
false
end
end
def withdraw(amount)
if amount > 0 && amount <= @balance
@balance -= amount
log_transaction("取款", amount)
true
elsif amount > @balance
puts "余额不足"
false
else
puts "取款金额必须大于0"
false
end
end
def transfer_to(other_account, amount)
if withdraw(amount)
other_account.deposit(amount)
puts "转账成功: #{amount} 到 #{other_account.owner}"
end
end
def self.total_accounts
@@total_accounts
end
def info
"账户: #{@account_number}, 户主: #{@owner}, 余额: #{@balance}"
end
private
def generate_account_number
"ACC#{rand(100000..999999)}"
end
def log_transaction(type, amount)
timestamp = Time.now.strftime("%Y-%m-%d %H:%M:%S")
puts "[#{timestamp}] #{type}: #{amount}, 余额: #{@balance}"
end
end
# 使用银行账户系统
account1 = BankAccount.new("张三", 1000)
account2 = BankAccount.new("李四", 500)
puts account1.info
puts account2.info
account1.deposit(200)
account1.withdraw(150)
account1.transfer_to(account2, 300)
puts "总账户数: #{BankAccount.total_accounts}"🎯 面向对象最佳实践
1. 单一职责原则
ruby
# 好的设计:每个类只有一个职责
class User
attr_accessor :name, :email
def initialize(name, email)
@name = name
@email = email
end
end
class UserValidator
def self.valid_email?(email)
email.match?(/\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i)
end
end
class UserPersistence
def self.save(user)
# 保存用户到数据库
end
end2. 封装性
ruby
class Temperature
def initialize(celsius)
self.celsius = celsius
end
def celsius
@celsius
end
def celsius=(value)
raise ArgumentError, "温度不能低于绝对零度(-273.15°C)" if value < -273.15
@celsius = value
end
def fahrenheit
@celsius * 9.0 / 5.0 + 32
end
def fahrenheit=(value)
self.celsius = (value - 32) * 5.0 / 9.0
end
end
temp = Temperature.new(25)
puts temp.celsius # 25
puts temp.fahrenheit # 77.0
temp.fahrenheit = 86
puts temp.celsius # 30.03. 继承层次设计
ruby
# 抽象基类
class Shape
def area
raise NotImplementedError, "子类必须实现area方法"
end
def perimeter
raise NotImplementedError, "子类必须实现perimeter方法"
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
class Circle < Shape
def initialize(radius)
@radius = radius
end
def area
Math::PI * @radius ** 2
end
def perimeter
2 * Math::PI * @radius
end
end
# 使用多态
shapes = [
Rectangle.new(5, 3),
Circle.new(4)
]
shapes.each do |shape|
puts "面积: #{shape.area.round(2)}, 周长: #{shape.perimeter.round(2)}"
end📚 下一步学习
掌握了Ruby类和对象后,建议继续学习:
- Ruby 面向对象 - 深入学习面向对象编程概念
- Ruby 继承与多态 - 学习更高级的继承特性
- Ruby 模块(Module) - 掌握模块化编程
- Ruby 设计模式 - 学习常见的设计模式
继续您的Ruby学习之旅吧!