Ruby 中的子类构造函数

问题描述

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

我没有弄清楚如何使用 class 方法自动创建子类,但使用 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

有没有办法使用类方法构建子类并将其传递像 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 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 的对象,例如带有类方法的模块:

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