在Java中,当有人问:

什么是多态性?

重载或重写是可以接受的答案吗?

我认为事情远不止如此。

如果你有一个抽象基类,它定义了一个没有实现的方法,并且你在子类中定义了这个方法,这仍然是覆盖的吗?

我认为超负荷肯定不是正确的答案。


当前回答

import java.io.IOException;

class Super {

    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName() + " - I'm parent");
        return null;
    }

}

class SubOne extends Super {

    @Override
    protected Super getClassName(Super s)  {
        System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
        return null;
    }

}

class SubTwo extends Super {

    @Override
    protected Super getClassName(Super s) throws NullPointerException {
        System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
        return null;
    }

}

class SubThree extends Super {

    @Override
    protected SubThree getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
        return null;
    }

}

class SubFour extends Super {

    @Override
    protected Super getClassName(Super s) throws IOException {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
        return null;
    }

}

class SubFive extends Super {

    @Override
    public Super getClassName(Super s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
        return null;
    }

}

class SubSix extends Super {

    public Super getClassName(Super s, String ol) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
        return null;
    }

}

class SubSeven extends Super {

    public Super getClassName(SubSeven s) {
        System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
        return null;
    }

}

public class Test{

    public static void main(String[] args) throws Exception {

        System.out.println("Overriding\n");

        Super s1 = new SubOne(); s1.getClassName(null);

        Super s2 = new SubTwo(); s2.getClassName(null);

        Super s3 = new SubThree(); s3.getClassName(null);

        Super s4 = new SubFour(); s4.getClassName(null);

        Super s5 = new SubFive(); s5.getClassName(null);

        System.out.println("Overloading\n");

        SubSix s6 = new SubSix(); s6.getClassName(null, null);

        s6 = new SubSix(); s6.getClassName(null);

        SubSeven s7 = new SubSeven(); s7.getClassName(s7);

        s7 = new SubSeven(); s7.getClassName(new Super());

    }
}

其他回答

重写更像是通过声明一个与上层方法(超级方法)具有相同名称和签名的方法来隐藏一个继承的方法,这为类添加了多态行为。 换句话说,选择要调用的级别方法的决定将在运行时而不是在编译时做出。 这就引出了接口和实现的概念。

具体地说重载或重写并没有给出全貌。多态性就是对象根据其类型专门化其行为的能力。

我不同意这里的一些答案,因为重载是一种多态形式(参数多态),在这种情况下,具有相同名称的方法可以具有不同的行为,给出不同的参数类型。一个很好的例子是操作符重载。您可以定义“+”来接受不同类型的参数——例如字符串或int型——并且基于这些类型,“+”将具有不同的行为。

多态性还包括继承和重写方法,尽管它们在基类型中可以是抽象的或虚拟的。在基于继承的多态性方面,Java只支持单个类继承,将其多态行为限制为单个基类型链。Java支持多个接口的实现,这是另一种形式的多态行为。

我觉得你们的概念混在一起了。多态性是对象在运行时表现不同的能力。要实现这一点,您需要两个必要条件:

后期绑定 继承。

重载与覆盖的意思不同,这取决于你所使用的语言。例如,在Java中不存在重写,而是重载。子类中可以使用对其基类具有不同签名的重载方法。否则它们将被重写(请注意,我的意思是现在没有办法从对象外部调用基类方法)。

然而,在c++中却不是这样。任何重载方法,无论签名是否相同(不同的量,不同的类型),都可以被重写。也就是说,当从子类对象外部调用基类的方法时,基类的方法在子类中显然不再可用。

所以答案是在Java中使用重载。在任何其他语言中都可能不同,因为它发生在c++中

多态性涉及到一种语言通过使用单一接口统一处理不同对象的能力;因此,它与覆盖有关,因此接口(或基类)是多态的,实现者是覆盖的对象(同一奖章的两个面)

无论如何,这两个术语之间的区别可以用其他语言更好地解释,比如c++:如果基本函数是虚的,那么c++中的多态对象的行为就像Java对应的对象一样,但如果方法不是虚的,那么代码跳转是静态解析的,并且在运行时不检查真实类型,因此,多态包括对象根据用于访问它的接口而表现不同的能力;让我在伪代码中做一个例子:

class animal {
    public void makeRumor(){
        print("thump");
    }
}
class dog extends animal {
    public void makeRumor(){
        print("woff");
    }
}

animal a = new dog();
dog b = new dog();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

(假设makeRumor不是虚拟的)

Java并没有真正提供这种级别的多态性(也称为对象切片)。

动物a =新狗(); Dog b = new Dog ();

a.makeRumor() -> prints thump
b.makeRumor() -> prints woff

在这两种情况下,它只会打印woff.. 因为a和b指的是类dog

表达多态性最清晰的方法是通过抽象基类(或接口)

public abstract class Human{
   ...
   public abstract void goPee();
}

这个类是抽象的,因为goPee()方法对人类是不可定义的。它只对子类Male和Female可定义。此外,人是一个抽象的概念——你不能创造一个既不是男性也不是女性的人。一定是两者之一。

因此,我们通过使用抽象类来延迟实现。

public class Male extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Stand Up");
    }
}

and

public class Female extends Human{
...
    @Override
    public void goPee(){
        System.out.println("Sit Down");
    }
}

现在我们可以让一屋子的人去尿尿了。

public static void main(String[] args){
    ArrayList<Human> group = new ArrayList<Human>();
    group.add(new Male());
    group.add(new Female());
    // ... add more...

    // tell the class to take a pee break
    for (Human person : group) person.goPee();
}

运行该命令会得到:

Stand Up
Sit Down
...