问题描述
尝试用 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