联合类型作为方法重载替代

时间:2018-04-28 01:14:35

标签: javascript java typescript overloading union-types

概述

我正在尝试使用TypeScript在Java中编写等效的重载方法,并且无法判断在这种特定情况下使用union types是否提供任何值,而不是使用单独的函数名称。这个概念与JavaScript(以及其他语言)相关,其中变量可以具有任何类型,而不是两种指定类型。

带方法重载的Java

假设我想重载基本方法,例如下面的内容。

void expectPickedApples(String treeName, int expectedAppleCount) {
   assert(pickApples(treeName) == expectedAppleCount);
}

void expectPickedApples(int treeIndex, int expectedAppleCount) {
   expectPickedApples(getTreeName(treeIndex), expectedAppleCount);
}

TypeScript选项

现在假设我想要一种我不能重载方法的语言中的相同功能,但是我可以使用联合类型,例如TypeScript。同样,这可能适用于JavaScript或其他变量类型为任何语言的语言。

不同的功能名称(选项1)

我可以简单地使用不同的函数名称,如下所示:

function expectPickedApplesForTreeName(treeName: string, expectedAppleCount: number) {
   expect(pickApples(treeName)).toBe(expectedAppleCount);
}

function expectPickedApplesForTreeIndex(treeIndex: number, expectedAppleCount: number) {
   getTreeName(treeIndex).then(treeName => {
      expectPickedApplesForTreeName(treeName, expectedAppleCount);
   });
}

联盟类型(选项2)

我使用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是否需要修改或者树名失败(获取名称应该有自己的测试,但也许是对服务的调用)我可能不相信)。

0 个答案:

没有答案