Ruby 面向对象

在 Ruby 中,面向对象编程(OOP) 是其核心设计哲学之一。Ruby 是纯面向对象的语言,一切皆对象(包括数字、字符串等基本类型)。以下是对 Ruby 面向对象编程的中文讲解,涵盖类、对象、继承、模块、方法等关键概念,力求简洁清晰。


1. 基本概念

  • 类(Class):定义对象的蓝图,包含属性(实例变量)和行为(方法)。
  • 对象(Object):类的实例,通过调用类的 new 方法创建。
  • 一切皆对象:在 Ruby 中,数字(如 1)、字符串(如 "hello")等都是对象,可以调用方法。
  puts 1.class  # 输出:Integer
  puts "hello".class  # 输出:String

2. 定义类与创建对象

定义类

使用 class 关键字定义类,类名通常首字母大写(CamelCase)。

class Person
  def initialize(name, age)  # 构造函数
    @name = name  # 实例变量
    @age = age
  end

  def introduce
    "Hi, I'm #{@name}, #{@age} years old."
  end
end

创建对象

通过 new 方法创建类的实例。

person = Person.new("Alice", 25)
puts person.introduce  # 输出:Hi, I'm Alice, 25 years old.

说明

  • initialize 是构造函数,创建对象时自动调用。
  • @name@age 是实例变量,存储对象的状态。

3. 属性访问

Ruby 使用 attr_accessor, attr_reader, attr_writer 定义属性访问方法。

  • attr_accessor:生成 getter 和 setter。
  class Person
    attr_accessor :name, :age  # 自动生成 name, name=, age, age= 方法
    def initialize(name, age)
      @name = name
      @age = age
    end
  end

  person = Person.new("Bob", 30)
  puts person.name  # 输出:Bob
  person.age = 31
  puts person.age   # 输出:31
  • attr_reader:仅生成 getter。
  • attr_writer:仅生成 setter。

手动定义 getter/setter

class Person
  def name
    @name
  end
  def name=(value)
    @name = value
  end
end

4. 类方法与实例方法

  • 实例方法:作用于对象,由实例调用。
  class Person
    def say_hello
      "Hello!"
    end
  end
  person = Person.new
  puts person.say_hello  # 输出:Hello!
  • 类方法:作用于类本身,使用 self.class << self 定义。
  class Person
    def self.info
      "This is the Person class."
    end
  end
  puts Person.info  # 输出:This is the Person class.

5. 继承

Ruby 支持单一继承,类通过 < 继承父类。

class Student < Person
  def initialize(name, age, grade)
    super(name, age)  # 调用父类的 initialize
    @grade = grade
  end

  def introduce
    super + " I'm in grade #{@grade}."  # 重写父类方法
  end
end

student = Student.new("Charlie", 15, 10)
puts student.introduce  # 输出:Hi, I'm Charlie, 15 years old. I'm in grade 10.

说明

  • super 调用父类的同名方法。
  • Ruby 不支持多重继承,但通过模块(Mixin)实现类似功能。

6. 模块与 Mixin

模块(Module)用于代码复用和命名空间管理,不能实例化,但可以通过 includeextend 混入类。

Mixin 示例

module Greetable
  def greet
    "Hello from #{self.class}!"
  end
end

class Person
  include Greetable
end

class Robot
  include Greetable
end

person = Person.new
robot = Robot.new
puts person.greet  # 输出:Hello from Person!
puts robot.greet   # 输出:Hello from Robot!

说明

  • include:模块方法成为类的实例方法。
  • extend:模块方法成为类的类方法。

7. 访问控制

Ruby 提供三种访问控制修饰符:

  • public:默认,方法可被任何人调用。
  • private:方法只能在类内部或实例方法中调用。
  • protected:方法可被同一类的实例或子类实例调用。
class Person
  def initialize(name)
    @name = name
  end

  def public_method
    puts "This is public."
    private_method
  end

  private
  def private_method
    puts "This is private."
  end

  protected
  def protected_method
    puts "This is protected."
  end
end

person = Person.new("Alice")
person.public_method      # 输出:This is public. This is private.
# person.private_method    # 错误:private method
# person.protected_method  # 错误:protected method

说明

  • private 方法不能通过实例显式调用。
  • protected 方法允许同一类实例之间调用。

8. 类变量与实例变量

  • 实例变量(@var:每个对象独有。
  class Person
    def initialize(name)
      @name = name
    end
  end
  • 类变量(@@var:类及其子类共享。
  class Person
    @@count = 0
    def initialize
      @@count += 1
    end
    def self.count
      @@count
    end
  end
  Person.new
  Person.new
  puts Person.count  # 输出:2

9. 单例方法

单例方法是为特定对象定义的方法,不影响其他对象。

person = Person.new("Alice")
def person.unique_method
  puts "I'm unique!"
end
person.unique_method  # 输出:I'm unique!
# Person.new.unique_method  # 错误:undefined method

10. 动态特性

Ruby 是动态语言,支持运行时修改类和对象。

  • 重定义方法
  class Person
    def say
      "Original"
    end
  end
  class Person
    def say
      "Redefined"
    end
  end
  puts Person.new.say  # 输出:Redefined
  • method_missing:处理未定义方法。
  class Person
    def method_missing(name, *args)
      puts "未找到方法:#{name}"
    end
  end
  Person.new.unknown  # 输出:未找到方法:unknown

11. 注意事项

  • 一切皆对象:Ruby 中没有基本类型,所有值都是对象。
  • 单一继承:Ruby 只支持单一继承,使用模块实现多重继承效果。
  • 动态性:支持运行时修改类和对象,但需谨慎,避免代码不可预测。
  • 命名规范
  • 类/模块:CamelCase(如 MyClass)。
  • 方法:snake_case(如 my_method)。
  • 性能:大量动态操作(如 method_missing)可能影响性能。
  • 访问控制:明确使用 privateprotected 提高代码安全性。

12. 示例:综合应用

module Loggable
  def log(message)
    puts "[LOG] #{message}"
  end
end

class Person
  include Loggable
  attr_accessor :name
  @@count = 0

  def initialize(name)
    @name = name
    @@count += 1
    log("Created person: #{name}")
  end

  def self.count
    @@count
  end
end

class Student < Person
  def initialize(name, grade)
    super(name)
    @grade = grade
  end
end

# 测试
person = Person.new("Alice")
student = Student.new("Bob", 10)
puts person.name  # 输出:Alice
puts Person.count  # 输出:2
person.log("Test")  # 输出:[LOG] Test

13. 总结

Ruby 的面向对象编程以类、对象和模块为核心,强调一切皆对象和动态性。类通过 initialize 定义对象,模块通过 Mixin 实现代码复用,继承和访问控制增强了代码组织。Ruby 的动态特性(如 method_missing)提供了灵活性,但需注意性能和可维护性。结合模块和异常处理,Ruby 的 OOP 适合快速开发和复杂系统设计。

如果你有具体问题或需要更详细的示例,请告诉我!

类似文章

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注