我是新手 oop.so 我只是在尝试一些东西。下面的问题只是一个虚构的问题,但它可以帮助我更清楚地理解 oop。
我正在编码制作一个计算器,它只能加乘十进制数和二进制数。
所以我有一个名为计算器的抽象类和两个子类 - 二进制计算器和十进制计算器
我的计算器类中有两个抽象函数 - add(),multiply()
现在的问题是,只有十进制add()函数确实将三个数字相加,其余的只对两个数字执行。
所以现在我有点困惑,我应该在 deciamCalculator 类中制作两个构造函数,还是应该只创建 4 个单独的子类 - drciamAddingCalculator、十进制乘法计算器、二进制添加计算器和 二进制乘法计算器
我也不明白为什么十进制计算器需要 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 方法,对吧? 您可以先按添加按钮,然后输入数字(一次一位数字),然后按等于按钮。 在按下等于之前不会进行数学运算,并且计算器需要存储按下哪个数字和哪个操作的知识。
因此,在这种情况下,我们不是传入一个带有每个操作方法的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
我可以继续说下去,但这应该足以引起人们的思考。