问题描述
我是oop的新手,所以我只是在尝试一些东西。下面的问题只是一个虚构的问题,但是它可以帮助我更清楚地了解oop。
我正在编写一个计算器,只能将十进制数和二进制数相加。
所以我有一个名为Calculator的抽象类和两个子类-binaryCalculator和decimalCalculator
我的Calculator类中有两个抽象函数-add(),multiple()
现在的问题是,只有十进制add()函数确实将三个数字相加,其余的仅对两个数字执行。
所以现在我有点困惑,我应该在deciamCalculator类中创建两个构造函数还是应该只创建4个单独的子类-drciamAddingCalculator,decimalMultiplyingCalculator,binaryAddingCalculator和 binaryMultiplyingCalculator
解决方法
我也不明白为什么十进制计算器需要3个数字,但是一种可能的方法是让add()
和multiply()
取任意数量的数字并将它们全部相加/相乘
Javacript示例:
class DecimalCalulator extends AbstractCalculator {
add(...numbers: number[]): number {
return numbers.reduce((sum,n) => sum + n);
}
multiply(...numbers: number[]): number {
return numbers.reduce((product,n) => product * n);
}
}
请注意,这些方法可以是static
,因此我们已经开始质疑为什么这是一个类以及该类的实例代表什么。
如果实例已将以前的数字存储为属性,则add()
和multiply()
应该仅使用一个数字,并且应是void
的方法,用于修改储值。
class AbstractCalculator {
protected total: number = 0;
/*... */
}
class DecimalCalulator extends AbstractCalculator {
add(number: number): void {
this.total += number;
}
multiply(number: number): void {
this.total *= number;
}
}
除了经典继承之外,还有很多方法可以考虑这一点。如果不想,根本不需要使用继承。
也许BinaryOperations
和DecimalOperations
中的一个被传递到Calculator
的构造函数中并存储为实例变量this.operations
。
现在,Calculator
类的唯一职责是存储滚动汇总并在调用操作时对其进行更新。它可以具有clear()
和undo()
之类的方法。它不知道实际的数学运算,因为它将其委托给this.operations.add()
。请注意,Operations
接口在这里本质上是static
,因此有进一步思考的空间。
interface Operations {
add(...numbers: number[]): number;
multiply(...numbers: number[]): number;
}
class Calculator {
private total: number;
private readonly operations: Operations;
constructor( operations: Operations ) {
this.total = 0;
this.operations = operations;
}
clear(): void {
this.total = 0;
}
add( number: number ): void {
this.total = this.operations.add(this.total,number);
}
multiply( number: number ): void {
this.total = this.operations.multiply(this.total,number);
}
}
如果这是一个交互式计算器,请考虑调用操作的顺序。您不只是在调用带数字的add方法,对吗?您将先按添加按钮,然后输入数字(一次输入一位数字),然后按等于按钮。在按下equals之前,不会进行任何数学运算,并且计算器需要存储有关按下了哪个数字和哪个操作的知识。
因此,在这种情况下,我们可能会传入一个Operations
处理程序数组,其中一个操作具有一个Operation
或一个,而不是为每个操作都传递一个带有方法的key
对象。 symbol
(在存储最后按下的按钮时使用)和callback
,在适当的时候调用。
interface ButtonHandler {
symbol: string;
callback( previousValue: number,enteredValue: number ): number;
}
const DecimalAdd: ButtonHandler = {
symbol: '+',callback: ( a,b ) => a + b,} // this is a plain javascript object,not a class,but it implements out interface
我可以继续,但是那应该足够让我思考。