简体   繁体   English

C#和Java中的方法重载

[英]Method overloading in C# and Java

I ran the following methods in C#. 我在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;
}

Here, if I call Add(1,1) , it gives ambiguity. 在这里,如果我调用Add(1,1) ,它会产生歧义。 Now let me swap position of float and long in the first method as follows: 现在让我在第一个方法中交换floatlong位置,如下所示:

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;
}

Now it prints "method 2" as output. 现在它打印“方法2”作为输出。 What is the reason behind the ambiguity in first case? 第一种情况模棱两可的原因是什么?

And if I write following two methods in my code: 如果我在我的代码中编写以下两种方法:

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;
}

On calling Add(1,1) , it gives ambiguity error. 在调用Add(1,1) ,它会产生歧义错误。 Why does it not go for best match, which is the second method (having int and float )? 为什么它不是最佳匹配,这是第二种方法(有intfloat )? According to me, it should have given method 2 as output. 据我说,它应该给出方法2作为输出。

From the C# specification , 7.5.3.2 Better Function member : C#规范7.5.3.2 Better Function成员

Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN }, MP is defined to be a better function member than MQ if 给定一个参数列表A,其中包含一组参数表达式{E1,E2,...,EN}和两个适用的函数成员MP和MQ,参数类型为{P1,P2,...,PN}和{Q1,Q2, ...,QN},MP被定义为比MQ更好的函数成员if

  • for each argument, the implicit conversion from EX to QX is not better than the implicit conversion from EX to PX, and 对于每个参数,从EX到QX的隐式转换并不比从EX到PX的隐式转换更好
  • for at least one argument, the conversion from EX to PX is better than the conversion from EX to QX. 对于至少一个参数,从EX到PX的转换优于从EX到QX的转换。

Note that the specification uses the term implicit conversion in a way that includes identity conversions. 请注意,规范使用术语隐式转换 ,其方式包括身份转换。 See 6.1 Implicit conversions : 请参见6.1隐式转换

The following conversions are classified as implicit conversions: 以下转化归类为隐式转化:

  • Identity conversions 身份转换
  • Implicit numeric conversions 隐式数字转换
  • [...] [...]

And from 6.1.1 Identity conversion : 6.1.1身份转换

An identity conversion converts from any type to the same type. 身份转换从任何类型转换为相同类型。 [...] [...]


Your set of argument types is: 您的参数类型集是:

{ int, int }

In the first case, the candidates are: 在第一种情况下,候选人是:

{ float, long } 
{ int, float }

Let MP be the first candidate and MQ be the second candidate. 让MP成为第一个候选者,MQ成为第二个候选者。

  • There is one argument X (= 1) where the implicit conversion from EX to QX is better than the implicit conversion from EX to PX: int to int is better than int to float (because it's the same type). 有一个参数X(= 1)其中,从EX到QX的隐式转换从EX到PX的隐式转换更好: intint优于intfloat (因为它是相同的类型)。

Let MP be the second candidate and MQ be the first candidate. 让MP成为第二个候选者,MQ成为第一个候选者。

  • There is one argument X (= 2) where the implicit conversion from EX to QX is better than the implicit conversion from EX to PX: int to long is better than int to float . 有一个参数X(= 2)其中,从EX到QX的隐式转换从EX到PX的隐式转换更好: intlong优于intfloat

Neither candidate satisfies the first bullet. 两个候选人都不满足第一个子弹。 The tie breaking mechanisms that are described the specification are not applicable here (because neither method is generic, neither is variadic, neither has optional parameters, etc). 规范中描述的打破平局机制在这里不适用(因为这两种方法都不是通用的,也不是可变参数,也没有可选参数等)。 Thus, this call is ambiguous. 因此,这种呼吁是模棱两可的。


In the second case, the candidates are: 在第二种情况下,候选人是:

{ long, float }
{ int, float }

Let MP be the first candidate and MQ be the second candidate. 让MP成为第一个候选者,MQ成为第二个候选者。

  • There is one argument X (= 1) where the implicit conversion from EX to QX is better than the implicit conversion from EX to PX: int to int is better than int to long (because it's the same type). 有一个参数X(= 1)其中,从EX到QX的隐式转换从EX到PX的隐式转换更好: intint优于intlong (因为它是相同的类型)。

Let MP be the second candidate and MQ be the first candidate. 让MP成为第二个候选者,MQ成为第一个候选者。

  • There is no argument X where the implicit conversion from EX to QX is better than the implicit conversion from EX to PX. 没有参数X,从EX到QX的隐式转换优于从EX到PX的隐式转换。
  • There is one argument X (= 1) where the implicit conversion from EX to PX is better than the conversion from EX to QX: int to int is better than int to long . 有一个参数X(= 1)其中,从EX到PX的隐式转换从EX到QX转换更好: intint优于intlong

Since the second candidate satisfies both bullets, it is a better match than the first. 由于第二个候选人满足两个子弹,因此它比第一个更好。


In the third case, the candidates are: 在第三种情况下,候选人是:

{ long, long }
{ int, float } 

Just like in the first case: 就像第一种情况一样:

  • int to int is better than int to long . intint优于intlong
  • But int to long is better than int to float . int to longint更好float

Thus, the call is ambiguous again. 因此,呼叫再次模棱两可。


The Java Language Specification states in 15.12.2.5 Choosing the Most Specific Method : Java语言规范15.12.2.5指出选择最具体的方法

One applicable method m1 is more specific than another applicable method m2, for an invocation with argument expressions e1, ..., ek, if any of the following are true: 对于具有参数表达式e1,...,ek的调用,如果满足以下任何条件,则一个适用的方法m1比另一个适用的方法m2更具体:

  • m2 is generic, and m1 is inferred to be more specific than m2 for argument expressions e1, ..., ek by §18.5.4. m2是通用的,并且根据§18.5.4推断m1对于参数表达式e1,...,ek比m2更具体。
  • m2 is not generic, and m1 and m2 are applicable by strict or loose invocation, and where m1 has formal parameter types S1, ..., Sn and m2 has formal parameter types T1, ..., Tn, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ n, n = k). m2不是通用的,m1和m2适用于严格或松散的调用,并且m1具有形式参数类型S1,...,Sn和m2具有形式参数类型T1,...,Tn,类型Si更多对于所有i,参数ei的特定于Ti(1≤i≤n,n = k)。
  • m2 is not generic, and m1 and m2 are applicable by variable arity invocation, and where the first k variable arity parameter types of m1 are S1, ..., Sk and the first k variable arity parameter types of m2 are T1, ..., Tk, the type Si is more specific than Ti for argument ei for all i (1 ≤i≤k). m2不是通用的,m1和m2适用于变量arity调用,并且m1的前k个变量arity参数类型是S1,...,Sk和m2的前k个变量arity参数类型是T1,..对于所有i(1≤i≤k),对于参数ei,Si类型比Ti更具体。 Additionally, if m2 has k+1 parameters, then the k+1'th variable arity parameter type of m1 is a subtype of the k+1'th variable arity parameter type of m2. 另外,如果m2具有k + 1个参数,则m1的第k + 1个可变参数类型是第m + 1个可变参数类型m2的子类型。

The above conditions are the only circumstances under which one method may be more specific than another. 上述条件是一种方法可能比另一种方法更具体的唯一情况。

A type S is more specific than a type T for any expression if S <: T (§4.10). 如果S <:T(§4.10),则类型S对于任何表达式比类型T更具体。

Like before, please note that the relation described here includes the case where S and T are the same type, not strictly subtype of one another (which would be proper subtyping ). 和之前一样,请注意这里描述的关系包括S和T是相同类型的情况,而不是彼此的严格子类型 (这将是正确的子类型 )。

For primitive types, is described in 4.10.1 Subtyping among Primitive Types : 对于原始类型,在4.10.1原始类型中的子类型中描述:

The following rules define the direct supertype relation among the primitive types: 以下规则定义了基本类型之间的直接超类型关系:

  • double >1 float double> 1 float
  • float >1 long 漂浮> 1长
  • long >1 int 长> 1 int
  • int >1 char int> 1个字符
  • int >1 short int> 1短
  • short >1 byte 短> 1个字节

With these, the overload resolution rules are effectively the same as with C# for this particular case. 有了这些,对于这种特殊情况,重载决策规则实际上与C#相同。 The previous explanation is applicable. 前面的解释是适用的。

In this case the compiler look for the method which closest matches the input variable(s) 在这种情况下,编译器会查找与输入变量最匹配的方法

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;
}

Add(1,1) this method is not clear which version should be choose, so for solving this problem(float or int in the first parameter, long or float in second one) you have to specify type of one of inputs parameter in method 添加(1,1)这个方法不清楚应该选择哪个版本,所以为了解决这个问题(第一个参数中的float或int,long或第二个参数中的float)你必须在方法中指定一个输入参数的类型

  Add(1F, 1);
  Add(1, 1F);

But following code ,compiler consider int type as closest matche for number 1 in the first method parameter 但是在下面的代码中,编译器将int类型视为第一个方法参数中数字1的最接近的matche

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;
}

so If you want to call the first method you should do this 所以如果你想调用第一种方法,你应该这样做

Add(1L, 1);

And for third part of you code 而对于你的第三部分代码

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;
}

again it is not clear which version complier should use, because of second input parameter in your method(float or long), so for solving this issue you have to specify the input 再次不清楚哪个版本编译器应该使用,因为你的方法中的第二个输入参数(float或long),所以为了解决这个问题,你必须指定输入

    Add(1L, 1);//method 1
    Add(1, 1F);// method 2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM