繁体   English   中英

子类中的方法可以重载超类中的方法吗?

[英]Can a method in sub class overloading a method in super class?

Java代码:

class P {
    public void hello() {}
}

class C extends P {
    public void hello(String s) {}
}

我的问题是: C类中的hello是否重载了超类P中的同名?

我的朋友说他们不是因为他们不在同一个班级。

采用更正式的方法,Java 7 的 Java 语言规范指出:

如果一个类的两个方法(无论是在同一个类中声明,还是都由一个类继承,或者一个声明一个继承)具有相同的名称但签名不是覆盖等效的,则该方法名称被称为超载。

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.4.9

我会把你的朋友指向这个链接。

因此,简而言之,在您的示例中, hello 方法确实是重载的。

简单说明:

我认为这个问题的出现是因为有时我们会听到以下内容,

"方法重载在类内部进行。方法覆盖发生在两个具有继承关系的类中。 "

上述说法是正确的。 但是你的朋友错了。 为什么?

因为当你扩展一个类时,子类拥有超类定义的所有方法。 就好像超类的所有方法都被子类实现了一样。 这意味着 hello() 方法也已由 C 类实现。 现在,您在 C 类中添加了一个具有不同参数 (hello(String s)) 的方法。 这意味着,C 类共有两个名称相同但参数不同的方法,即“重载”。

希望它是晶莹剔透的。

是的,你的朋友错了,因为他只考虑了压倒一切的概念。

但是这里hello()hello(String s)的参数不同,所以它是重载而不是覆盖。

重载可以发生在同一个类以及父子类关系中,而覆盖仅发生在继承关系中。

困惑之源:如果您谈论的是 C++ 而不是 Java,那么您的朋友是对的。 在 C++ 中,函数重载只能发生在同一类的成员之间。 而在 Java 中,除此之外,还可能在具有继承关系的两个类之间发生重载。

长话短说, C的实例将同时提供hello()hello(String s)方法。 P的实例将只有hello方法可用。

这确实是重载,因为您有两个同名的方法采用不同的参数。

但是,它不是覆盖,因为覆盖是在子类中声明的方法与超类中的方法具有相同的名称和相同的参数

例如,如果你有

class C extends P {
    public void hello() {}
}

它将覆盖P中声明的hello()方法。 在这种情况下调用new C().hello()时,您将调用类C中声明的hello()方法的实现。

Yes it is overloading ,这种重载发生在扩展P的类“ C ”的情况下,因此有two methods with the same namdifferent parameters的方法,导致Class C中方法hello()的重载。 但是, Class P只能访问其定义中存在的方法之一。

这是一个有效的问题,因为通常在同一个类中使用两个具有相同名称(但参数不同)的方法来解释重载。

我认为是的,由于“is a”关系, C中的方法hello重载了Phello方法。

“is a”关系表明,由于 C 是 P 的子类,它也是 P 的一个实例(“C is a P”)。 因此 C 有 2 个重载的hello方法。

好问题!!!在子类中如果方法名 | 参数类型 | 列表被更改然后子类方法将不会被视为覆盖它被视为重载方法示例:

class A{
void m1(int a){}
}

class B extends A{
  void m1(float f)
   {}
}

在上面的程序中,m1 方法是一个重载方法。

是的,我们可以在子类中重载超类方法,如下所示:

    public class OverLoading {

    public static void main(String[] args) {
        B b = new B();
        b.display();
        b.display(4);
    }
}


class A {
    public void display() {
        System.out.println("A class display method");
    }
}

class B extends A {
    public void display() {
        System.out.println("class B subclass");
    }

    public void display(int a) { //Overloading in subclass
        System.out.println("class B subclass with overloading");
    }
}
Output: 
class B subclass
class B subclass with overloading

取决于班级。 从类 P 的角度来看(如果引用是 P,则对象可以是 C)它不是。 如果你写这样的东西: P p = new C(); 没有重载,因为您不能调用p.hello("foo")

从 C 类的角度来看,它是重载的,因为如果你写C c = new C(); 它有两个名称相同但签名不同的方法。

这是一个很好的问题,但答案有点棘手。

的确,您可以将继承的方法从父类重载到子类中。 然而,有趣的是,实际行为取决于引用变量的类型。

让我们考虑以下示例:

public class OverLoadingTest {

    public static void main(String[] args) {
        ChildClass cc = new ChildClass();
        SuperClass sc = cc;
        sc.method("lol");
        cc.method("lol");
    }

    static class SuperClass {

        public void method(Object o) {
            System.out.println("SuperClass called.");
        }
    }

    static class ChildClass extends SuperClass {
        public void method(String s) {
            System.out.println("ChildClass called.");
        }
    }
}

所以,我们有一个类扩展了另一个类,并且有一个从父类重载方法的方法。

很容易猜到,如果你有一个ChildClass的实例,这两个方法就会被重载,并且重载决议会像往常一样发生。

但是,让我们考虑创建ChildClass的实例并将其分配给SuperClass类型的引用变量。 超载的东西还在吗?

如果你执行这个程序,你会得到这个输出:

SuperClass called.
ChildClass called.

输出清楚地表明在这种情况下这里没有过载。 然而,这可以通过覆盖原始方法来改变。

static class ChildClass extends SuperClass {
    public void method(String s) {
        System.out.println("ChildClass called.");
    }

    public void method(Object o) {
        System.out.println("ChildClass called.");
    }
}

现在,如果您再次运行该程序,您将得到以下输出:

ChildClass called.
ChildClass called.

解释

现在,为什么 JVM 会这样呢? 为什么在我们使用子类的实例时看不到重载方法?

这将带我们了解 JVM 如何调用方法。 JVM 看到您使用SuperClass类型的引用来引用对象,因此,它只能使用与该类型相关的方法,唯一的例外是被覆盖的方法。 而且由于method(String)没有覆盖,我们拥有父级的method(Object) ,因此,它是选择执行的方法。

然后我们重写该方法来打破这个规则,这就是 JVM 调用ChildClass.method(Object)的方式,即使引用变量是父类的。

重载是指您有两个名称相同但签名不同的方法(您的情况)。

旁注:覆盖是当您有两个具有完全相同的签名和名称以及父类的方法时。

暂无
暂无

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

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