对于当代语言,它只是语法糖。以完全与语言无关的方式,不仅如此。
以前,此答案仅说明它不仅仅是语法糖,但是如果您在注释中看到,Falco提出了一个观点,即现代语言似乎都消失了,这是一个谜。他们不会将方法重载与动态确定在同一步骤中调用哪个函数混合在一起。稍后将对此进行澄清。
这就是为什么它应该更多的原因。
考虑一种同时支持方法重载和无类型变量的语言。您可以具有以下方法原型:
bool someFunction(int arg);
bool someFunction(string arg);
在某些语言中,您可能会被屈服于在编译时知道给定的代码行将调用其中之一。但是在某些语言中,并非所有变量都被键入(或者它们都隐式地键入为as Object
或其他类型),因此,请想象构建一个字典,其键映射到不同类型的值:
dict roomNumber; // some hotels use numbers, some use letters, and some use
// alphanumerical strings. In some languages, built-in dictionary
// types automatically use untyped values for their keys to map to,
// so it makes more sense then to allow for both ints and strings in
// your code.
现在,如果您想申请someFunction
这些房间号之一怎么办?您称之为:
someFunction(roomNumber[someSortOfKey]);
被someFunction(int)
称为还是被someFunction(string)
称为?在这里,您将看到一个示例,其中这些方法并非完全正交,尤其是在高级语言中。该语言必须在运行时确定要调用其中之一,因此它仍必须至少将它们视为相同的方法。
为什么不简单地使用模板?为什么不简单地使用无类型的参数呢?
灵活性和更细粒度的控制。有时使用模板/无类型参数是一种更好的方法,但有时并非如此。
您必须考虑以下情况:例如,您可能有两个方法签名,每个方法签名都带有an int
和a string
作为参数,但是每个签名的顺序不同。您可能有充分的理由执行此操作,因为每个签名的实现可能在很大程度上做相同的事情,但是只是略有不同。例如,日志记录可能不同。或者,即使它们执行相同的操作,您也可以仅从指定参数的顺序中自动收集某些信息。从技术上讲,您可以只使用伪开关语句来确定传入的每个参数的类型,但这很麻烦。
那么下一个例子是不好的编程习惯吗?
bool stringIsTrue(int arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(Object arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
bool stringIsTrue(string arg)
{
if (arg == "0")
{
return false;
}
else
{
return true;
}
}
是的,总的来说。在这个特定的示例中,它可以使某人避免尝试将其应用于某些原始类型并恢复意外行为(这可能是一件好事)。但是,假设我缩写了上面的代码,并且实际上,您对所有基本类型和Object
s 都有重载。那么下面的代码确实更合适:
bool stringIsTrue(untyped arg)
{
if (arg.toString() == "0")
{
return false;
}
else
{
return true;
}
}
但是,如果仅需要将其用于int
s和string
s,又希望它根据相应的更简单或更复杂的条件返回true,该怎么办?那么您就有充分的理由使用重载:
bool appearsToBeFirstFloor(int arg)
{
if (arg.digitAt(0) == 1)
{
return true;
}
else
{
return false;
}
}
bool appearsToBeFirstFloor(string arg)
{
string firstCharacter = arg.characterAt(0);
if (firstCharacter.isDigit())
{
return appearsToBeFirstFloor(int(firstCharacter));
}
else if (firstCharacter.toUpper() == "A")
{
return true;
}
else
{
return false;
}
}
但是,为什么不只给这些函数两个不同的名称呢?您仍然具有相同数量的细粒度控制,不是吗?
因为,如前所述,有些酒店使用数字,有些使用字母,有些使用数字和字母的混合体:
appearsToBeFirstFloor(roomNumber[someSortOfKey]);
// will treat ints and strings differently, without you having to write extra code
// every single spot where the function is being called
这仍然与我在现实生活中使用的代码并不完全相同,但是它应该可以说明我的观点。
但是...这就是为什么它不只是当代语言中的语法糖。
Falco在评论中指出,当前的语言基本上不会在同一步骤中混合使用方法重载和动态函数选择。我以前理解某些语言的工作方式是,可以appearsToBeFirstFloor
在上面的示例中重载,然后该语言将在运行时根据未类型化变量的运行时间值确定要调用的函数版本。造成这种混乱的部分原因是使用ECMA等多种语言(例如ActionScript 3.0),您可以在其中轻松随机地在运行时在特定代码行上调用哪个函数。
如您所知,ActionScript 3不支持方法重载。对于VB.NET,可以在不显式分配类型的情况下声明和设置变量,但是当您尝试将这些变量作为参数传递给重载方法时,它仍然不希望读取运行时值来确定要调用的方法。相反,它希望找到带有类型Object
或无类型参数或类似参数的方法。因此,上面的int
vs. string
示例也无法在该语言中使用。C ++存在类似的问题,因为当您使用诸如void指针之类的东西或类似的其他机制时,它仍然需要您在编译时手动消除类型的歧义。
因此,正如第一个标题所说的...
对于当代语言,它只是语法糖。以完全与语言无关的方式,不仅如此。像上面的示例一样,使方法重载更加有用和相关,实际上可能是添加到现有语言中的一个不错的功能(正如AS3广泛要求的那样),或者它还可以用作许多不同的基本支柱之一。创建新的过程/面向对象语言。