这是重载,不同类中具有相同名称和不同签名的方法吗?

Posted

技术标签:

【中文标题】这是重载,不同类中具有相同名称和不同签名的方法吗?【英文标题】:Is this Overloading, methods with same name in different classes and different signature? 【发布时间】:2013-02-23 20:15:48 【问题描述】:

如果我在 Java 中有以下代码:

class A 

    public int add(int a , int b) 
        return (a+b);
    


class B extends A 
    public float add(float a , float b) 
        return (a+b);

在这种特殊情况下,子类并没有完全覆盖基类的 add 函数,因为它们具有不同的签名,并且仅当它们处于相同范围内时才会出现重载的概念。那么,子类B中的函数add(float , float)是不是被当作一个全新的函数,重载和覆盖的概念不适用呢?它使用“静态绑定”还是“动态绑定”?

【问题讨论】:

非常说明:programcreek.com/2009/02/… 【参考方案1】:

类b中的方法add是类a中add的重载。不是覆盖。覆盖只是原始 add 方法的不同实现。

【讨论】:

但我知道,当且仅当函数在相同的范围或类中时,重载的概念才会起作用。这就是造成混乱的原因【参考方案2】:

简而言之,是的。要覆盖,您需要复制完整的方法签名,其中包括方法名称、参数和返回类型。来自the tutorial

子类中具有相同签名的实例方法(名称,加 参数的数量和类型)和返回类型作为 超类中的实例方法会覆盖超类的方法。

您可能需要考虑@Override annotation,如果您没有成功覆盖方法,它将触发编译器错误。

在这个特定的例子中,您可能不需要像一些包括泛型在内的解决方案那样重写。所以你可以实例化一个类a<Integer>和一个类似的类a<Float>

【讨论】:

所以你说 b 类中的 add(float , float) 是一个完全不同的函数,与 a 类中的 add 函数无关。在这种情况下,重载或覆盖都在这里发挥作用。 也许吧。你没有重写,你提供了一个不同的类,除了原来的方法之外还有一个重载方法,所以也许泛型解决方案在这里更合适【参考方案3】:

在这种情况下,您不会覆盖该方法,因为签名不同。

但是在 b 类中存在重载,因为您有两个同名但参数不同的方法(一个是 a 类,另一个是 b 类)

希望对你有帮助。

【讨论】:

但我知道,当且仅当函数在相同的范围或类中时,重载的概念才会起作用。这就是造成混乱的原因。【参考方案4】:

在子类中可以有一个方法没有被重写但被重载。这里的子类有两个 add() 方法。接受 int 参数的版本(未覆盖),以及接受 float 参数的重载方法 add()。

【讨论】:

【参考方案5】:

我认为在这种特殊情况下不会发生重载和覆盖,因为在重载和覆盖的情况下返回类型必须相同,因此在这种情况下既不会发生静态绑定也不会发生动态绑定。 在返回类型不同的情况下,方法重载是不可能的,因为编译器无法确定他需要调用哪个方法。

【讨论】:

【参考方案6】:

我知道这是迟到的答案,但我认为对于初学者来说这是一个重要的问题。

重载的一个关键点是它在继承中起作用。

接下来是Static bindingDynamic binding

它是静态绑定那么,为什么?

静态绑定

    Java 中的静态绑定发生在Compile time 期间。 privatefinalstatic 方法和变量使用静态绑定并由编译器绑定。 静态绑定使用类型(Java 中的类)信息进行绑定。

动态绑定

    Runtime 期间发生动态绑定。

    在运行时基于运行时对象绑定的动态方法。

    动态绑定使用 Object 来解析绑定。

但重要的部分在这里

重载的方法使用静态绑定进行绑定,而重写的方法在运行时使用动态绑定进行绑定。

Java 编译器根据用于调用方法的参数类型确定要在编译时执行的重载方法的正确版本,这两个类的重载方法的参数接收调用中使用的参数值并执行重载方法。

B a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);

因此,如果您将创建类型 B 的引用,那么它将搜索正确的参数类型 对于上面的代码,它将执行这两种方法。

A a=new B();
a.add(4, 5);
a.add(4.0f, 5.0f);

但是对于上面的代码,它会给出浮点参数的编译时错误。

希望它能消除所有疑虑。

【讨论】:

【参考方案7】:

第一件事

是方法覆盖吗?

不,因为要覆盖一个方法,您需要复制完整的方法签名,正如 Brian Agnew 的回答中指出的那样,正如我在下面解释的那样。

是否超载?

是的,方法“add”在 B 类中有一个重载实现。

考虑以下代码:

class C
    public static void main(String args[])
        B a = new B();
        a.add(2 , 3);
        a.add(2.0 , 3.0);
    


class A 

    public int add(int a , int b) 
        System.out.print("INT ");
        return a + b;
    


class B extends A 
    public double add(double a , double b) 
        System.out.print("Double ");
        return a + b;
    

输出:INT 双精度

所以,代码中 Class B 中的方法重载了它从父级继承的 add 方法

它使用静态绑定还是动态绑定?

这就是让我得出结论认为 OP 很困惑的原因。它是静态绑定,因为它是一个重载函数。考虑动态绑定的唯一方法是在下面的场景中

class C
    public static void main(String args[])
        A a = new B();
        a.add(2.0 , 3.0);
    


class A 

    public int add(int a , int b) 
        System.out.println("A : INT");
        return a + b;
    


class B extends A 
    public int add(int a , int b) 
        System.out.println("B : INT");    
        return a + b;
    
        
    public double add(double a , double b) 
        System.out.println("Double");
        return a + b;
       

输出:B:INT

在这里,父类 A 有一个契约,上面写着“我有一个整数的添加行为”。 B 类继承了这种添加行为并使其更加具体,同时还提供了一种可以添加双精度的新行为。 但是 A 类“不知道这种行为”。

因此,A 类的对象“不能”添加双打。为此,您需要更具体的 A 对象类型,即 B 对象。

【讨论】:

虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review【参考方案8】:

A类中的方法add()也可以通过继承提供给B类,因此通过将数据类型从int, int更改为float, float,类中的方法为overloaded

【讨论】:

我认为这并不能真正回答问题。提问者知道重载和覆盖。【参考方案9】:

当且仅当函数在同一作用域或类中时,重载的概念才会起作用。 cz 如果这是方法重载的情况,那么对于相同的方法签名或相同的参数类型,编译器会感到困惑并且必须给出编译时错误。 但是在上面的 B 类程序中,如果你以相同的顺序传递相同的参数,那么根据重载它必须给出错误但它没有发生你可以检查它我已经有。 这是继承的情况,如果您调用任何方法,编译器将通过对象引用在子类中检查它,如果它不存在,那么它将查看上述程序的全部内容的父类。 希望这会有所帮助。

【讨论】:

请注意大小写和标点符号。这个答案很难理解

以上是关于这是重载,不同类中具有相同名称和不同签名的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

虚函数与重载函数的区别

方法重写与重载

方法签名最佳实践 - 重载与长名称

重载与重写的区别

C#中具有相同名称和签名但返回类型不同的方法

C#中具有相同名称和签名但返回类型不同的方法