C#和Java中的方法重载

Gau*_*ain 5 c# java oop overloading

我在C#中运行了以下方法.

public float Add(float num1, long num2)
{
    Console.WriteLine("method 1");
    return 0;
}
public float Add(int num1, float num2)
{
    Console.WriteLine("method 2");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里,如果我打电话Add(1,1),它会给出歧义.现在让我掉的位置float,并long在第一种方法如下:

public float Add(long num1, float num2)
{
    Console.WriteLine("method 1");
    return 0;
}
public float Add(int num1, float num2)
{
    Console.WriteLine("method 2");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

现在它打印"方法2"作为输出.第一种情况模棱两可的原因是什么?

如果我在我的代码中编写以下两种方法:

public float Add(long num1, long num2)
{
    Console.WriteLine("method 1"); 
    return 0;
}
public float Add(int num1, float num2)
{
    Console.WriteLine("method 2");
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在调用时Add(1,1),它会产生歧义错误.为什么它不是最佳匹配,这是第二种方法(拥有intfloat)?据我说,它应该给出方法2作为输出.

The*_*kis 9

C#规范,7.5.3.2 Better Function成员:

给定一个参数列表A,其中包含一组参数表达式{E1,E2,...,EN}和两个适用的函数成员MP和MQ,参数类型为{P1,P2,...,PN}和{Q1,Q2, ...,QN},MP被定义为比MQ更好的函数成员if

  • 对于每个参数,从EX到QX的隐式转换并不比从EX到PX的隐式转换更好
  • 对于至少一个参数,从EX到PX的转换优于从EX到QX的转换.

请注意,规范使用术语隐式转换,其方式包括身份转换.请参见6.1隐式转换:

以下转化归类为隐式转化:

  • 身份转换
  • 隐式数字转换
  • [...]

6.1.1身份转换:

身份转换从任何类型转换为相同类型.[...]


您的参数类型集是:

{ int, int }
Run Code Online (Sandbox Code Playgroud)

在第一种情况下,候选人是:

{ float, long } 
{ int, float }
Run Code Online (Sandbox Code Playgroud)

让MP成为第一个候选者,MQ成为第二个候选者.

  • 有一个参数X(= 1)其中,从EX到QX的隐式转换比从EX到PX的隐式转换更好:intint优于intfloat(因为它是相同的类型).

让MP成为第二个候选者,MQ成为第一个候选者.

  • 有一个参数X(= 2)其中,从EX到QX的隐式转换比从EX到PX的隐式转换更好:intlong优于intfloat.

两个候选人都不满足第一个子弹.规范中描述的打破平局机制在这里不适用(因为这两种方法都不是通用的,也不是可变参数,也没有可选参数等).因此,这种呼吁是模棱两可的.


在第二种情况下,候选人是:

{ long, float }
{ int, float }
Run Code Online (Sandbox Code Playgroud)

让MP成为第一个候选者,MQ成为第二个候选者.

  • 有一个参数X(= 1)其中,从EX到QX的隐式转换比从EX到PX的隐式转换更好:intint优于intlong(因为它是相同的类型).

让MP成为第二个候选者,MQ成为第一个候选者.

  • 没有参数X,从EX到QX的隐式转换优于从EX到PX的隐式转换.
  • 有一个参数X(= 1)其中,从EX到PX的隐式转换比从EX到QX的转化更好:intint优于intlong.

由于第二个候选人满足两个子弹,因此它比第一个更好.


在第三种情况下,候选人是:

{ long, long }
{ int, float } 
Run Code Online (Sandbox Code Playgroud)

就像第一种情况一样:

  • intint优于intlong.
  • 但是int,以long优于intfloat.

因此,呼叫再次模棱两可.


Java语言规范在国家15.12.2.5选择最具体方法:

对于具有参数表达式e1,...,ek的调用,如果满足以下任何条件,则一个适用的方法m1比另一个适用的方法m2更具体:

  • m2是通用的,并且根据§18.5.4推断m1对于参数表达式e1,...,ek比m2更具体.
  • m2不是通用的,m1和m2适用于严格或松散的调用,并且m1具有形式参数类型S1,...,Sn和m2具有形式参数类型T1,...,Tn,类型Si更多对于所有i,参数ei比Ti更具体(1≤i≤n,n = k).
  • m2不是通用的,m1和m2适用于变量arity调用,并且m1的前k个变量arity参数类型是S1,...,Sk和m2的前k个变量arity参数类型是T1,..对于所有i(1≤i≤k),对于参数ei,Si类型比Ti更具体.另外,如果m2具有k + 1个参数,则m1的第k + 1个可变参数类型是第m + 1个可变参数类型m2的子类型.

上述条件是一种方法可能比另一种方法更具体的唯一情况.

如果S <:T(§4.10),则类型S对于任何表达式比类型T更具体.

和之前一样,请注意这里描述的关系包括S和T是相同类型的情况,而不是彼此的严格子类型(这将是正确的子类型).

对于原始类型,在4.10.1原始类型中的子类型中描述:

以下规则定义了基本类型之间的直接超类型关系:

  • double> 1 float
  • 漂浮> 1长
  • 长> 1 int
  • int> 1个字符
  • int> 1短
  • 短> 1个字节

有了这些,对于这种特殊情况,重载决策规则实际上与C#相同.前面的解释是适用的.