Ruby 中的子类构造函数

Subclasses constructor in Ruby

尝试用 classes 在 Ruby 中构建一个可编程计算器,它可以通过各种操作进行扩展。逻辑:首先用Calculator.new初始化计算器class,然后将命令添加为子class,如Calculator.new.add_command (“+”, ClassName).

我未能弄清楚如何使用 class 方法自动创建子 classes,但通过 Ruby 的内置 public_send method,所以代码看起来像这样:

class Calculator 
attr_accessor :num1, :calc

def initialize(num1)
    @num1 = num1 
    @calc = []
end

def compute(operation, num)
    if @calc.length == 0
       @calc[0] = @num1.public_send(operation, num)
    else 
       @calc[0] = @calc[0].public_send(operation, num)
    end
end

def result
    @calc[0]
end
end
cal = Calculator.new(1)
cal.compute(:+, 1)
p cal.result => 2

有没有办法用 class 方法构建子 classes 并向它们传递像 public_send 这样的功能?

此外,计算器也不是传统的计算器:在初始化阶段它应该接受一个参数,即第一个数字,接下来的每个操作都应该接受第二个数字并与前一个操作的结果一起工作。喜欢:

Calculator.new(1) 
cal.compute(“+”, 2) => 1 + 2 =  3 
cal.compute(“-”, 1) =>  3 - 1 = 2
cal.compute(“**”, 2) => 2 ** 2 = 4 

您可以使用哈希 (@commands) 将操作映射到它们各自的 class 或模块:

class Calculator
  attr_accessor :num1, :calc

  def initialize(num1)
    @num1 = num1
    @calc = []
    @commands = {}
  end

  def add_command(operation, callable)
    @commands[operation] = callable
  end

  # ...
end

您还需要对方法名称进行一些约定,让我们选择 call:

class Calculator
  # ...

  def compute(operation, num)
    if @calc.length == 0
      @calc[0] = @commands[operation].call(@num1, num)
    else
      # ...
    end
  end

  # ...
end

现在您只需要一个响应 call 的对象,例如具有 class 方法的模块:

module Addition
  def self.call(a, b)
    a + b
  end
end

要将 Addition 添加为 :+ 操作:

cal = Calculator.new(2)
cal.add_command(:+, Addition)
cal.compute(:+, 3)
cal.result #=> 5

您还可以添加一个 proc / lambda 因为它们也响应 call:

cal = Calculator.new(2)
cal.add_command :+, ->(a, b) { a + b }
cal.compute(:+, 3)
cal.result #=> 5