MST
星途 面试题库

面试题:Ruby中的模块与类设计原则

在Ruby中,模块常用于将相关功能分组,类则用于定义对象的结构和行为。请阐述如何依据Ruby的代码哲学与设计原则,合理使用模块来实现代码的复用与解耦,以及如何设计一个遵循开闭原则(Open - Closed Principle)的类,举例说明。
24.4万 热度难度
编程语言Ruby

知识考点

AI 面试

面试题答案

一键面试

使用模块实现代码复用与解耦

  1. 模块的混入(Mixin)
    • 在Ruby中,可以通过include关键字将模块混入到类中,从而实现代码复用。例如,假设有一个Logger模块,提供日志记录功能:
module Logger
  def log(message)
    puts "#{Time.now}: #{message}"
  end
end

class User
  include Logger
  def initialize(name)
    @name = name
  end
  def greet
    log("User #{@name} is greeting")
  end
end

user = User.new('John')
user.greet
  • 这里User类通过混入Logger模块,获得了log方法,实现了日志记录功能的复用,同时将日志记录功能与User类本身的业务逻辑解耦。
  1. 模块作为命名空间
    • 模块可以作为命名空间,避免命名冲突。例如,有两个不同功能的模块MathUtilsStringUtils
module MathUtils
  def add(a, b)
    a + b
  end
end

module StringUtils
  def capitalize(str)
    str.capitalize
  end
end

class MyApp
  include MathUtils
  include StringUtils
  def perform
    result = add(2, 3)
    text = capitalize('hello')
    puts "Addition result: #{result}, Capitalized text: #{text}"
  end
end

app = MyApp.new
app.perform
  • 这两个模块分别定义了不同的方法,通过作为命名空间,在MyApp类中可以清晰地复用这些方法,不会产生命名冲突。

设计遵循开闭原则的类

开闭原则要求类对扩展开放,对修改关闭。例如,设计一个图形绘制系统:

  1. 定义抽象图形类
class Shape
  def draw
    raise NotImplementedError, 'Subclasses must implement draw method'
  end
end
  1. 定义具体图形类
class Circle < Shape
  def initialize(radius)
    @radius = radius
  end
  def draw
    puts "Drawing a circle with radius #{@radius}"
  end
end

class Rectangle < Shape
  def initialize(width, height)
    @width = width
    @height = height
  end
  def draw
    puts "Drawing a rectangle with width #{@width} and height #{@height}"
  end
end
  1. 使用图形类
shapes = []
shapes << Circle.new(5)
shapes << Rectangle.new(10, 5)

shapes.each do |shape|
  shape.draw
end
  • 这里Shape类定义了一个抽象的draw方法,具体的图形类CircleRectangle继承自Shape类并实现draw方法。如果要添加新的图形,比如Triangle,只需要创建一个新的类继承自Shape并实现draw方法,而不需要修改现有的Shape类或其他具体图形类的代码,符合开闭原则。