MST
星途 面试题库

面试题:Ruby模块中如何有效实现代码复用

在Ruby中,模块常被用于提升代码复用性。请阐述模块中包含(include)、扩展(extend)和前置(prepend)这几种方法在实现代码复用方面的区别,并举例说明如何通过模块的方法定义及使用来复用代码。
15.7万 热度难度
编程语言Ruby

知识考点

AI 面试

面试题答案

一键面试

包含(include)、扩展(extend)和前置(prepend)的区别

  1. 包含(include)
    • 作用:将模块中的实例方法混入到类中,使得类的实例可以调用这些方法。它会把模块的实例方法添加到类的祖先链(ancestors chain)的较低位置,在类自身的实例方法之后。
    • 示例
module Greeting
  def say_hello
    puts "Hello!"
  end
end

class Person
  include Greeting
end

person = Person.new
person.say_hello # 输出 "Hello!"
  1. 扩展(extend)
    • 作用:将模块中的方法作为类的类方法使用,也可以将模块方法添加到对象的单例类(singleton class)中,使对象可以调用这些方法。它把模块的方法添加到类的祖先链的较高位置,在类自身的类方法之前。
    • 示例
module MathUtils
  def square(x)
    x * x
  end
end

class Calculator
  extend MathUtils
end

puts Calculator.square(5) # 输出 25
  1. 前置(prepend)
    • 作用:将模块中的实例方法混入到类中,但是与 include 不同,它把模块添加到类的祖先链的较高位置,在类自身的实例方法之前。这意味着如果类和模块有同名方法,模块中的方法会优先被调用。
    • 示例
module Logging
  def say_name
    puts "Logging: Before saying name"
    super
    puts "Logging: After saying name"
  end
end

class Animal
  def say_name
    puts "I am an animal"
  end
end

Animal.prepend Logging
animal = Animal.new
animal.say_name
# 输出:
# Logging: Before saying name
# I am an animal
# Logging: After saying name

通过模块方法定义及使用复用代码示例

  1. 模块定义及类使用示例
    • 模块定义
module Utility
  def format_number(number)
    format("%.2f", number)
  end

  def reverse_string(str)
    str.reverse
  end
end
  • 类使用
class DataProcessor
  include Utility

  def process_data(number, string)
    formatted_number = format_number(number)
    reversed_string = reverse_string(string)
    puts "Formatted number: #{formatted_number}, Reversed string: #{reversed_string}"
  end
end

processor = DataProcessor.new
processor.process_data(123.456, "hello")
# 输出:Formatted number: 123.46, Reversed string: olleh
  1. 模块作为类方法扩展示例
    • 模块定义
module FileUtils
  def read_file(file_path)
    File.read(file_path) if File.exist?(file_path)
  end

  def write_file(file_path, content)
    File.write(file_path, content)
  end
end
  • 类使用
class FileOperator
  extend FileUtils
end

FileOperator.write_file('test.txt', 'This is a test')
puts FileOperator.read_file('test.txt')