Ruby 面向对象编程入门
面向对象编程基础概念
在深入 Ruby 的面向对象编程之前,让我们先回顾一些基本概念。面向对象编程(OOP)是一种编程范式,它将程序组织成一组相互协作的对象,每个对象都代表现实世界中的某个实体或概念。在 OOP 中,主要有以下几个核心概念:
类(Class)
类是对象的蓝图或模板。它定义了对象的属性(数据)和方法(行为)。例如,我们要创建一个 “人” 的类,类中可能会有姓名、年龄等属性,以及说话、走路等方法。在 Ruby 中,定义一个类的语法如下:
class Person
# 这里可以定义属性和方法
end
对象(Object)
对象是类的实例。根据 “人” 这个类,我们可以创建出具体的某个人,比如 “张三”“李四” 等,这些具体的人就是对象。在 Ruby 中,可以使用 new
方法来创建对象:
class Person
end
person1 = Person.new
属性(Attribute)
属性是对象所具有的数据。以 “人” 类为例,姓名、年龄就是属性。在 Ruby 中,可以通过实例变量来表示属性。实例变量以 @
符号开头,例如:
class Person
def initialize(name, age)
@name = name
@age = age
end
end
person1 = Person.new('张三', 25)
在上面的代码中,@name
和 @age
就是 Person
对象的属性,通过 initialize
方法在创建对象时进行初始化。
方法(Method)
方法是对象能够执行的操作或行为。还是以 “人” 类为例,说话、走路等就是方法。在 Ruby 中定义方法的语法如下:
class Person
def speak
puts "我叫 #{@name},今年 #{@age} 岁。"
end
end
person1 = Person.new('张三', 25)
person1.speak
上述代码中,speak
方法就是 Person
类的一个方法,它使用了对象的属性 @name
和 @age
来输出信息。
Ruby 中的类定义
基本类定义
在 Ruby 中,定义一个类非常简单,使用 class
关键字,后面跟上类名,类名通常采用驼峰命名法(CamelCase)。类的定义以 end
关键字结束。例如,定义一个简单的 Dog
类:
class Dog
def bark
puts "汪汪汪!"
end
end
在这个 Dog
类中,我们定义了一个 bark
方法,当调用这个方法时,会输出 “汪汪汪!”。
初始化方法(initialize)
初始化方法是一个特殊的方法,当使用 new
方法创建对象时,会自动调用这个方法。它通常用于设置对象的初始状态,比如初始化属性。以下是在 Dog
类中添加初始化方法的示例:
class Dog
def initialize(name, breed)
@name = name
@breed = breed
end
def bark
puts "#{@name}(#{@breed})汪汪汪!"
end
end
dog1 = Dog.new('小白', '博美')
dog1.bark
在上述代码中,initialize
方法接受两个参数 name
和 breed
,并将它们分别赋值给实例变量 @name
和 @breed
。bark
方法则使用这些属性来输出更详细的信息。
类变量和类方法
类变量是属于类本身的变量,而不是属于类的实例(对象)。类变量以 @@
符号开头。类方法是定义在类上而不是对象上的方法。以下是一个包含类变量和类方法的示例:
class Dog
@@total_dogs = 0
def initialize(name, breed)
@name = name
@breed = breed
@@total_dogs += 1
end
def bark
puts "#{@name}(#{@breed})汪汪汪!"
end
def self.total_dogs
@@total_dogs
end
end
dog1 = Dog.new('小白', '博美')
dog2 = Dog.new('小黑', '拉布拉多')
puts "总共有 #{Dog.total_dogs} 只狗。"
在这个例子中,@@total_dogs
是类变量,用于统计创建的 Dog
对象的总数。self.total_dogs
是类方法,用于获取类变量的值。
Ruby 中的对象
创建对象
正如前面所提到的,在 Ruby 中使用 new
方法来创建对象。例如,创建一个 Car
类的对象:
class Car
def initialize(model, color)
@model = model
@color = color
end
def info
puts "这是一辆 #{@color} 颜色的 #{@model} 汽车。"
end
end
car1 = Car.new('奔驰 C 级', '黑色')
car1.info
上述代码创建了一个 Car
类的对象 car1
,并调用了 info
方法来输出汽车的信息。
对象的属性访问
在 Ruby 中,我们可以通过访问器方法(getter 和 setter 方法)来访问和修改对象的属性。
- Getter 方法:用于获取属性的值。我们可以手动定义,也可以使用
attr_reader
来自动生成。例如:
class Person
attr_reader :name
def initialize(name)
@name = name
end
end
person1 = Person.new('张三')
puts person1.name
在上述代码中,attr_reader :name
自动生成了一个 name
方法,用于获取 @name
的值。
- Setter 方法:用于设置属性的值。同样,可以手动定义,也可以使用
attr_writer
来自动生成。例如:
class Person
attr_writer :name
def initialize
@name = nil
end
end
person1 = Person.new
person1.name = '李四'
在上述代码中,attr_writer :name
自动生成了一个 name=
方法,用于设置 @name
的值。
如果既需要获取又需要设置属性的值,可以使用 attr_accessor
,它同时生成 getter 和 setter 方法:
class Person
attr_accessor :name
def initialize
@name = nil
end
end
person1 = Person.new
person1.name = '王五'
puts person1.name
继承
继承的概念
继承是面向对象编程中的一个重要概念,它允许一个类(子类)从另一个类(父类)中获取属性和方法。子类可以复用父类的代码,并且可以根据需要添加或修改自己的属性和方法。在 Ruby 中,使用 <
符号来表示继承关系。例如:
class Animal
def speak
puts "动物发出声音。"
end
end
class Dog < Animal
def bark
puts "汪汪汪!"
end
end
dog1 = Dog.new
dog1.speak
dog1.bark
在上述代码中,Dog
类继承自 Animal
类,所以 Dog
对象可以调用 Animal
类的 speak
方法,同时也有自己的 bark
方法。
重写方法
子类可以重写父类的方法,以提供更具体或不同的实现。例如:
class Animal
def speak
puts "动物发出声音。"
end
end
class Dog < Animal
def speak
puts "汪汪汪!"
end
end
dog1 = Dog.new
dog1.speak
在这个例子中,Dog
类重写了 Animal
类的 speak
方法,当调用 dog1.speak
时,会执行 Dog
类中重写后的方法。
super 关键字
在子类重写父类方法时,如果需要调用父类的方法,可以使用 super
关键字。例如:
class Animal
def speak
puts "动物发出声音。"
end
end
class Dog < Animal
def speak
super
puts "汪汪汪!"
end
end
dog1 = Dog.new
dog1.speak
在上述代码中,Dog
类的 speak
方法先调用了父类的 speak
方法(通过 super
),然后再输出 “汪汪汪!”。
多态
多态的概念
多态是指同一个方法调用,在不同的对象上会有不同的行为。这是通过继承和方法重写来实现的。例如,我们有一个 Shape
类,以及它的子类 Circle
和 Rectangle
,每个子类都有自己的 area
方法实现:
class Shape
def area
raise NotImplementedError, "子类必须实现 area 方法"
end
end
class Circle < Shape
def initialize(radius)
@radius = radius
end
def area
Math::PI * @radius * @radius
end
end
class Rectangle < Shape
def initialize(width, height)
@width = width
@height = height
end
def area
@width * @height
end
end
shapes = [Circle.new(5), Rectangle.new(4, 6)]
shapes.each do |shape|
puts "面积是 #{shape.area}"
end
在上述代码中,shapes
数组包含了 Circle
和 Rectangle
对象,当调用 shape.area
时,会根据对象的实际类型(Circle
或 Rectangle
)来调用相应的 area
方法,这就是多态的体现。
封装
封装的概念
封装是将数据和操作数据的方法包装在一起,对外隐藏对象的内部实现细节,只提供必要的接口来与对象进行交互。在 Ruby 中,通过访问控制符来实现一定程度的封装。
访问控制符
- public:公共方法,可以在任何地方调用。默认情况下,Ruby 中的方法都是
public
的。例如:
class Person
def speak
puts "我在说话。"
end
end
person1 = Person.new
person1.speak
- private:私有方法,只能在对象内部调用,不能从外部调用。可以使用
private
关键字来声明私有方法。例如:
class Person
def speak
puts "我在说话。"
private_method
end
private
def private_method
puts "这是私有方法。"
end
end
person1 = Person.new
person1.speak
# person1.private_method # 这行代码会报错,因为不能从外部调用私有方法
- protected:受保护方法,只能在对象内部以及子类对象内部调用。可以使用
protected
关键字来声明受保护方法。例如:
class Animal
protected
def protected_method
puts "这是受保护方法。"
end
end
class Dog < Animal
def bark
protected_method
end
end
dog1 = Dog.new
dog1.bark
# Animal.new.protected_method # 这行代码会报错,因为不能从外部调用受保护方法
模块(Module)
模块的概念
模块是一种组织代码的方式,它可以包含方法、常量等。与类不同的是,模块不能实例化,它主要用于提供可复用的代码片段,避免命名冲突,以及实现混入(mixin)功能。
定义模块
在 Ruby 中,使用 module
关键字来定义模块,模块名通常采用大写字母开头的驼峰命名法。模块的定义以 end
关键字结束。例如:
module Utility
def self.square(x)
x * x
end
end
result = Utility.square(5)
puts result
在上述代码中,Utility
模块定义了一个类方法 square
,可以通过模块名来调用这个方法。
混入(Mixin)
混入是指将模块中的方法添加到类中,使得类可以使用模块中的方法。在 Ruby 中,使用 include
关键字来实现混入。例如:
module Flyable
def fly
puts "我在飞。"
end
end
class Bird
include Flyable
end
bird1 = Bird.new
bird1.fly
在上述代码中,Bird
类通过 include Flyable
将 Flyable
模块混入,从而 Bird
对象可以调用 fly
方法。
总结
通过以上内容,我们对 Ruby 的面向对象编程有了较为深入的了解。从类和对象的基本概念,到继承、多态、封装等重要特性,再到模块的使用,这些知识构成了 Ruby 面向对象编程的核心。掌握这些内容,将有助于我们编写更加结构化、可维护和可复用的 Ruby 代码,无论是开发小型脚本还是大型应用程序,都能得心应手。希望大家在实践中不断探索和运用这些知识,提升自己的编程能力。