我正在尝试使用TypeScript在Java中编写等效的重载方法,并且无法判断在这种特定情况下使用union types是否提供任何值,而不是使用单独的函数名称。这个概念与JavaScript(以及其他语言)相关,其中变量可以具有任何类型,而不是两种指定类型。
假设我想重载基本方法,例如下面的内容。
void expectPickedApples(String treeName, int expectedAppleCount) {
assert(pickApples(treeName) == expectedAppleCount);
}
void expectPickedApples(int treeIndex, int expectedAppleCount) {
expectPickedApples(getTreeName(treeIndex), expectedAppleCount);
}
现在假设我想要一种我不能重载方法的语言中的相同功能,但是我可以使用联合类型,例如TypeScript。同样,这可能适用于JavaScript或其他变量类型为任何语言的语言。
我可以简单地使用不同的函数名称,如下所示:
function expectPickedApplesForTreeName(treeName: string, expectedAppleCount: number) {
expect(pickApples(treeName)).toBe(expectedAppleCount);
}
function expectPickedApplesForTreeIndex(treeIndex: number, expectedAppleCount: number) {
getTreeName(treeIndex).then(treeName => {
expectPickedApplesForTreeName(treeName, expectedAppleCount);
});
}
我使用union类型的解决方案如下所示:
function expectPickedApples(treeIdentifier: string | number, expectedAppleCount: number) {
if (typeof(treeIdentifier) === 'number') {
expect(pickApples(treeIdentifier)).toBe(expectedAppleCount);
} else {
getTreeName(treeIdentifier).then(treeName => {
expect(pickApples(treeName)).toBe(expectedAppleCount);
});
}
}
有些情况下,使用联合类型可以明显提供价值。但是,在这种情况下,我只使用带有类型的if语句来选择两个块中的一个。上面哪个选项是首选?还有更好的选择吗?
选项1提供了紧凑的功能和可测试性,但选项2提供了便利性和潜在的可读性。
如果我只调用这些函数并且没有实现,我会选择选项2,因为只有一个函数名要记住而且代码很简单(总是可以看到方法文档来记住参数含义)。
expectPickedApples('the old tree', 5);
expectPickedApples(3, 10);
而不是
expectPickedApplesForTreeName('the old tree', 5);
expectPickedApplesForTreeIndex(3, 10);
但是,如果我拥有此代码的实现,包括测试等职责,则选项1似乎更好。例如,识别错误的位置会更容易,例如在获取名称之前treeIndex是否需要修改或者树名失败(获取名称应该有自己的测试,但也许是对服务的调用)我可能不相信)。