继承和模块
1. 继承
1.1 什么是继承?
继承是面向对象编程中的一个重要概念,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承,子类可以重用父类的代码,并且可以添加新的属性和方法,或者覆盖父类的方法。
1.2 继承的语法
在 Ruby 中,使用 class 关键字定义一个类,并使用 < 符号表示继承关系。例如:
class Animal
def speak
puts "Some generic animal sound"
end
end
class Dog < Animal
def speak
puts "Woof!"
end
end
dog = Dog.new
dog.speak # 输出: Woof!
在这个例子中,Dog 类继承了 Animal 类。Dog 类中的 speak 方法覆盖了 Animal 类中的 speak 方法。
1.3 继承中的方法覆盖
子类可以覆盖父类的方法,也可以通过 super 关键字调用父类的方法。例如:
class Animal
def speak
puts "Some generic animal sound"
end
end
class Cat < Animal
def speak
super
puts "Meow!"
end
end
cat = Cat.new
cat.speak # 输出: Some generic animal sound
# 输出: Meow!
在这个例子中,Cat 类中的 speak 方法首先调用了父类 Animal 的 speak 方法,然后输出 "Meow!"。
2. 模块
2.1 什么是模块?
模块是 Ruby 中的一种组织代码的方式,它类似于类,但不能被实例化。模块主要用于封装一组相关的常量、方法和类。模块可以被其他类或模块包含(mixin),从而实现代码的复用。
2.2 模块的定义和使用
使用 module 关键字定义一个模块。例如:
module Greeting
def hello
puts "Hello!"
end
end
class Person
include Greeting
end
person = Person.new
person.hello # 输出: Hello!
在这个例子中,Greeting 模块定义了一个 hello 方法。Person 类通过 include 关键字将 Greeting 模块包含进来,从而可以使用 hello 方法。
2.3 模块的命名空间
模块还可以用作命名空间,避免类名冲突。例如:
module Math
class Calculator
def add(a, b)
a + b
end
end
end
calculator = Math::Calculator.new
puts calculator.add(2, 3) # 输出: 5
在这个例子中,Math 模块作为命名空间,Calculator 类被定义在 Math 模块中,避免了与其他 Calculator 类的冲突。
3. 混入 (Mixin) 技术
3.1 什么是混入?
混入(Mixin)是一种将模块的功能添加到类中的技术。通过 include 或 prepend 关键字,模块的方法可以被类直接使用,就像类的实例方法一样。
3.2 使用 include 和 prepend
include 将模块的方法作为类的实例方法,而 prepend 将模块的方法插入到类的继承链的前面。例如:
module Logging
def log(message)
puts "[LOG] #{message}"
end
end
class User
include Logging
def initialize(name)
@name = name
log("User #{@name} created")
end
end
user = User.new("Alice") # 输出: [LOG] User Alice created
在这个例子中,Logging 模块的 log 方法被 User 类包含,并在 initialize 方法中使用。
3.3 混入的顺序
include 和 prepend 的顺序会影响方法的查找顺序。include 的方法会在类的继承链的后面,而 prepend 的方法会在继承链的前面。例如:
module A
def foo
puts "A's foo"
end
end
module B
def foo
puts "B's foo"
end
end
class C
include A
include B
def foo
puts "C's foo"
end
end
c = C.new
c.foo # 输出: B's foo
在这个例子中,B 模块的 foo 方法覆盖了 A 模块的 foo 方法,因为 B 模块在 A 模块之后被包含。
4. 实践练习
4.1 练习:创建一个继承链
创建一个 Vehicle 类,然后创建 Car 和 Truck 类继承 Vehicle 类。每个类都有自己的 start 方法,并且 Truck 类覆盖 Vehicle 类的 start 方法。
class Vehicle
def start
puts "Vehicle started"
end
end
class Car < Vehicle
def start
puts "Car started"
end
end
class Truck < Vehicle
def start
super
puts "Truck started"
end
end
car = Car.new
car.start # 输出: Car started
truck = Truck.new
truck.start # 输出: Vehicle started
# 输出: Truck started
4.2 练习:使用模块实现混入
创建一个 Logger 模块,包含一个 log 方法。然后创建一个 Employee 类,包含 Logger 模块,并在 initialize 方法中使用 log 方法记录员工信息。
module Logger
def log(message)
puts "[LOG] #{message}"
end
end
class Employee
include Logger
def initialize(name, position)
@name = name
@position = position
log("Employee #{@name} (#{@position}) created")
end
end
employee = Employee.new("Bob", "Manager") # 输出: [LOG] Employee Bob (Manager) created
5. 总结
继承和模块是 Ruby 中实现代码复用和组织的重要工具。继承允许子类继承父类的属性和方法,而模块则通过混入技术将方法添加到类中。通过合理使用继承和模块,可以提高代码的可维护性和可扩展性。
希望这篇教程能帮助你更好地理解 Ruby 中的继承和模块。继续练习和探索,你将能够更熟练地使用这些强大的工具来构建复杂的应用程序。