Ruby 类和对象

Ruby 类和对象中文讲解

Ruby 是一种纯粹的面向对象编程语言,一切皆对象,包括数字、字符串等基本数据类型。类(Class)和对象(Object)是 Ruby 面向对象编程的核心。本文将详细讲解 Ruby 中的类和对象,涵盖定义、实例化、继承、方法、模块以及中文处理相关内容,基于 Ruby 3.4.x(截至 2025 年 8 月的最新稳定版)。本文适合初学者,同时提供中文相关注意事项。


1. 类和对象基础

  • 类(Class):类是对象的蓝图,定义了对象的属性(数据)和行为(方法)。
  • 对象(Object):对象是类的实例,通过类创建,包含特定数据和行为。
  • Ruby 的特性:每个对象都是某个类的实例,例如 "你好"String 类的对象,42Integer 类的对象。

示例:

# 检查对象所属类
puts "你好".class  # 输出: String
puts 42.class      # 输出: Integer

2. 定义类

使用 class 关键字定义类,类名通常以大写字母开头(遵循 Ruby 的命名规范)。

2.1 基本类定义
# encoding: UTF-8
class Person
  def initialize(name, age)  # 构造函数
    @name = name  # 实例变量
    @age = age
  end

  def introduce  # 实例方法
    "我叫#{@name},#{@age}岁"
  end
end
  • 说明
  • initialize 是构造函数,在创建对象时调用。
  • @name@age 是实例变量,存储对象的状态。
  • introduce 是实例方法,定义对象的行为。
2.2 创建对象

通过 new 方法实例化类:

# encoding: UTF-8
person = Person.new("小明", 20)
puts person.introduce  # 输出: 我叫小明,20岁

3. 实例变量和方法

  • 实例变量:以 @ 开头,属于特定对象,作用域为整个对象。
  • 实例方法:定义在类中,供对象调用。

示例:

# encoding: UTF-8
class Student
  def initialize(name, grade)
    @name = name
    @grade = grade
  end

  def study
    "#{@name} 正在学习,成绩:#{@grade}"
  end
end

student = Student.new("小红", "A")
puts student.study  # 输出: 小红 正在学习,成绩:A
3.1 访问器(Getter 和 Setter)

Ruby 提供便捷方式定义属性访问器:

  • 使用 attr_reader(只读)、attr_writer(只写)、attr_accessor(读写)。
# encoding: UTF-8
class Person
  attr_accessor :name, :age  # 自动生成 getter 和 setter

  def initialize(name, age)
    @name = name
    @age = age
  end
end

person = Person.new("小明", 20)
puts person.name  # 输出: 小明
person.age = 21   # 修改 age
puts person.age   # 输出: 21

4. 类变量和类方法

  • 类变量:以 @@ 开头,共享于类及其所有实例。
  • 类方法:使用 self.class << self 定义,属于类本身而非实例。

示例:

# encoding: UTF-8
class Person
  @@count = 0  # 类变量

  def initialize(name)
    @name = name
    @@count += 1
  end

  def self.total_count  # 类方法
    "总共创建了 #{@@count} 个 Person 对象"
  end
end

p1 = Person.new("小明")
p2 = Person.new("小红")
puts Person.total_count  # 输出: 总共创建了 2 个 Person 对象

5. 继承

Ruby 支持单继承,使用 < 指定父类,子类可以继承父类的属性和方法。

示例:

# encoding: UTF-8
class Person
  def initialize(name)
    @name = name
  end

  def introduce
    "我叫#{@name}"
  end
end

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

  def study
    "#{@name} 在学习,成绩:#{@grade}"
  end
end

student = Student.new("小红", "A")
puts student.introduce  # 输出: 我叫小红
puts student.study      # 输出: 小红 在学习,成绩:A
  • 说明
  • super 调用父类同名方法。
  • 子类可以扩展或重写父类方法。

6. 模块(Module)

模块用于组织代码或提供混入(Mixin)功能,不能直接实例化,但可被类包含。

6.1 定义模块
# encoding: UTF-8
module Greetable
  def say_hello
    "你好!"
  end
end
6.2 混入模块

使用 include 将模块混入类:

# encoding: UTF-8
class Person
  include Greetable
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

person = Person.new("小明")
puts person.say_hello  # 输出: 你好!
puts person.name       # 输出: 小明
6.3 模块作为命名空间

模块可用于避免命名冲突:

# encoding: UTF-8
module Chinese
  class Person
    def say
      "你好,我是中文 Person"
    end
  end
end

module English
  class Person
    def say
      "Hello, I am English Person"
    end
  end
end

zh = Chinese::Person.new
en = English::Person.new
puts zh.say  # 输出: 你好,我是中文 Person
puts en.say  # 输出: Hello, I am English Person

7. 中文处理相关内容

Ruby 对中文的支持依赖于正确的编码配置,以下是类和对象中处理中文的注意事项:

  1. 编码声明
  • 确保脚本以 UTF-8 保存并声明:
    ruby # encoding: UTF-8
  • Windows 用户若处理 GBK(旧系统),声明:
    ruby # encoding: GBK
  1. 中文实例变量和方法
   # encoding: UTF-8
   class Person
     def initialize(姓名)
       @姓名 = 姓名
     end

     def 介绍
       "你好,我的名字是#{@姓名}"
     end
   end

   person = Person.new("小明")
   puts person.介绍  # 输出: 你好,我的名字是小明
  • 注意:中文方法名合法但不推荐,建议使用英文以提高代码可读性。
  1. 中文字符串操作
  • 在类中处理中文字符串: # encoding: UTF-8 class TextProcessor def initialize(text) @text = text end def count_chinese @text.scan(/\p{Han}/).length end end processor = TextProcessor.new("你好,世界!") puts processor.count_chinese # 输出: 4(你好世界)
  1. 文件操作与中文
  • 保存对象数据到文件: # encoding: UTF-8 class Person attr_accessor :name def initialize(name) @name = name end def save_to_file File.write("person.txt", @name, encoding: "UTF-8") end end person = Person.new("小明") person.save_to_file
  1. 乱码问题
  • Windows CMD:默认 GBK 可能导致乱码,切换到 UTF-8:
    bash chcp 65001
  • 确保终端和文件编码一致,或使用 PowerShell/Windows Terminal。
  • 检查对象字符串编码:
    ruby puts person.name.encoding # 输出: UTF-8

8. 代码示例

  1. 完整类示例
   # encoding: UTF-8
   class Person
     @@count = 0
     attr_accessor :name, :age

     def initialize(name, age)
       @name = name
       @age = age
       @@count += 1
     end

     def introduce
       "我叫#{@name},#{@age}岁"
     end

     def self.total_count
       "总共创建了 #{@@count} 个对象"
     end
   end

   p1 = Person.new("小明", 20)
   p2 = Person.new("小红", 18)
   puts p1.introduce  # 输出: 我叫小明,20岁
   puts Person.total_count  # 输出: 总共创建了 2 个对象
  1. 继承与模块
   # encoding: UTF-8
   module Learnable
     def learn
       "学习中..."
     end
   end

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

   class Student < Person
     include Learnable
     def introduce
       "我是学生#{@name}"
     end
   end

   student = Student.new("小明")
   puts student.introduce  # 输出: 我是学生小明
   puts student.learn      # 输出: 学习中...

9. 常见问题与解决

  1. 中文乱码
  • 原因:脚本或终端编码不一致。
  • 解决
    • 添加 # encoding: UTF-8
    • Windows 用户运行:
      bash chcp 65001 set RUBYOPT=-EUTF-8
    • 使用 UTF-8 保存文件(无 BOM)。
  1. 实例变量未初始化
  • 原因:访问未定义的实例变量返回 nil
  • 解决
    ruby class Person def initialize @name ||= "默认姓名" # 设置默认值 end end
  1. 方法重写错误
  • 原因:子类意外覆盖父类方法。
  • 解决:使用 super 调用父类方法。

10. 最佳实践

  • 命名规范:类名使用驼峰式(CamelCase),方法和变量使用下划线(snake_case)。
  • 编码统一:始终使用 UTF-8,避免 GBK 除非必要。
  • 模块化:使用模块组织代码,增强复用性。
  • 访问控制
  • 使用 privateprotected 限制方法访问:
    ruby class Person private def secret "这是秘密" end end

11. 进阶建议

  • 学习 Rails:Rails 广泛使用类和对象(如模型类):
  class User < ApplicationRecord
    validates :name, presence: true
  end
  • 调试工具
  • 使用 pry 检查对象:
    bash gem install pry
    ruby require 'pry' person = Person.new("小明", 20) binding.pry # 检查 person.instance_variables
  • 国际化(i18n)
  • 在 Rails 中使用 i18n gem 处理中文:
    yaml # config/locales/zh-CN.yml zh-CN: hello: "你好"

12. 社区资源

通过以上讲解,你可以全面掌握 Ruby 的类和对象,并处理中文相关任务。如果需要深入某个主题(如继承、模块或 Rails 模型),请告诉我!

类似文章

发表回复

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