Skip to content

Ruby 类

Ruby 是一种纯粹的面向对象编程(Object-Oriented Programming, OOP)语言。核心 OOP 原则包括:

  • **数据封装(Data Encapsulation):**将数据(attributes,属性)和操作数据的方法(methods)捆绑在单个单元(object,对象)中。对内部状态的访问受到控制。
  • **数据抽象(Data Abstraction):**隐藏复杂的实现细节,只暴露对象的必要特性。
  • **多态(Polymorphism):**不同类的对象能够以各自类特定的方式响应同一消息(方法调用)的能力。
  • **继承(Inheritance):**允许一个新类(subclass,子类)继承现有类(superclass,超类)的属性和方法,促进代码复用并建立类之间的关系。

在 Ruby 中,一切皆对象。一个 class(类)是创建 object(对象)的蓝图。一个 object(对象)是 class 的一个实例(instance)。例如,如果 String 是一个类,那么 "hello" 就是一个对象(一个 String 的实例)。

类定义以 class 关键字开始,后跟类名(按照约定,类名必须以大写字母开头,例如 CamelCase),以 end 关键字结束。

class Vehicle
# Class content (attributes and methods) goes here
end

Ruby 在类的上下文中支持几种类型的变量:

  • **局部变量(Local Variables):**定义在方法内部。它们的作用域(scope)仅限于该方法。名称以小写字母或 _ 开头(例如 my_var)。
  • **实例变量(Instance Variables):**属于类的特定实例(对象)。它们保存对象的状态。名称以 @ 符号开头(例如 @color)。每个对象可以为其实例变量拥有不同的值。
  • **类变量(Class Variables):**在类的所有实例之间共享,也可以由类本身访问。名称以 @@ 开头(例如 @@count)。对类变量的修改对所有实例可见。使用时需谨慎,尤其是在继承场景下,它们的行为有时可能令人意外。
  • **全局变量(Global Variables):**程序中任何地方都可以访问。名称以 $ 符号开头(例如 $debug_mode)。全局变量应尽量少用,因为它们会使代码难以维护和调试。
#!/usr/bin/ruby
class Car
# Class variable to keep track of the number of cars created
@@number_of_cars = 0
# Shortcut for creating getter and setter methods for @color and @make
# attr_reader :color # Only getter
# attr_writer :color # Only setter
attr_accessor :color, :make # Both getter and setter
# The initialize method is a special constructor called when Car.new is invoked
def initialize(make, color)
@make = make # Instance variable
@color = color # Instance variable
@@number_of_cars += 1
puts "Initialized a #{@color} #{@make}."
end
# Instance method
def start_engine
puts "The #{@make}'s engine roars to life!"
end
# Class method (note the 'self.')
def self.total_cars_created
"Total cars created: #{@@number_of_cars}"
end
end
# Creating Objects (Instances of the Car class)
my_car = Car.new("Toyota", "Red")
her_car = Car.new("Honda", "Blue")
# Accessing instance variables (via attr_accessor)
puts "My car is a #{my_car.color} #{my_car.make}."
my_car.color = "Silver" # Using the setter
puts "My car is now #{my_car.color}."
# Calling instance methods
my_car.start_engine
her_car.start_engine
# Calling a class method
puts Car.total_cars_created

这将产生类似于以下的输出:

Initialized a Red Toyota.
Initialized a Blue Honda.
My car is a Red Toyota.
My car is now Silver.
The Toyota's engine roars to life!
The Honda's engine roars to life!
Total cars created: 2

initialize 方法是 Ruby 类中一个特殊的私有方法。当你使用 ClassName.new 创建新对象时,它会自动被调用。它主要用于通过为实例变量赋值来设置对象的初始状态。

实例方法(Instance Methods)和类方法(Class Methods):

Section titled “实例方法(Instance Methods)和类方法(Class Methods):”

**实例方法(Instance methods)**作用于类的实例(即对象)。它们可以访问对象的实例变量(例如 Car 示例中的 start_engine)。

**类方法(Class methods)**在类本身上调用,而不是在实例上调用。它们通过在方法名称前加上 self. 来定义(例如 self.total_cars_created)。它们无法访问实例的变量,但可以访问类变量。

属性访问器(Attribute Accessors):attr_reader, attr_writer, attr_accessor:

Section titled “属性访问器(Attribute Accessors):attr_reader, attr_writer, attr_accessor:”

Ruby 提供了方便的快捷方式来创建常用的实例变量的 Getter 和 Setter 方法:

  • attr_reader :variable_name 创建一个 Getter 方法(例如 def variable_name; @variable_name; end)。
  • attr_writer :variable_name 创建一个 Setter 方法(例如 def variable_name=(value); @variable_name = value; end)。
  • attr_accessor :variable_name 创建一个 Getter 和一个 Setter 方法。

使用这些访问器可以使代码更简洁和符合 Ruby 习惯。

方法可见性(Method Visibility):public, private, protected

Section titled “方法可见性(Method Visibility):public, private, protected”

Ruby 使用可见性关键字控制方法的访问:

  • public: 方法可以在任何地方访问。这是默认的可见性。
  • private: 方法只能由同一类实例内部的其他方法调用(隐式调用,即不带 self. 作为接收者,Setter 方法 self.foo = 除外)。子类或直接在对象上都无法访问它们。
  • protected: 方法可以由定义类及其子类的实例调用。它们可以带有显式接收者调用(例如 other_object.protected_method),只要 other_object 是调用者类的实例或其子类。
class BankAccount
attr_reader :balance
def initialize(initial_deposit)
@balance = initial_deposit
end
def deposit(amount)
@balance += amount
log_transaction("Deposit: #{amount}")
end
def withdraw(amount)
if can_withdraw?(amount)
@balance -= amount
log_transaction("Withdrawal: #{amount}")
else
puts "Insufficient funds!"
end
end
# Protected: Accessible by BankAccount and its subclasses
protected
def can_withdraw?(amount)
@balance >= amount
end
# Private: Only accessible within this BankAccount instance
private
def log_transaction(message)
puts "[LOG] #{Time.now}: #{message}, New Balance: #{@balance}"
end
end
account = BankAccount.new(100)
account.deposit(50)
account.withdraw(30)
# account.log_transaction("test") # This would raise NoMethodError (private)
# account.can_withdraw?(10) # This would raise NoMethodError (protected, if called from outside directly)

实际应用:

类和对象是大多数 Ruby 应用程序的基石。它们用于建模现实世界中的实体(如用户、产品、订单)、抽象概念(如数据库连接或文件解析器),以及组织代码以实现复用和可维护性。Ruby on Rails 等框架严重依赖基于类的结构(Model、View、Controller)。