在Java中,当有人问:

什么是多态性?

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

我认为事情远不止如此。

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

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


当前回答

术语重载指的是具有相同名称的东西的多个版本,通常是具有不同参数列表的方法

public int DoSomething(int objectId) { ... }
public int DoSomething(string objectName) { ... }

这些函数可能做同样的事情但你可以选择用ID或名称来调用它。与继承、抽象类等无关。

覆盖通常指的是多态性,就像你在问题中描述的那样

其他回答

没有:

重载是指使用相同的函数名,但接受不同的参数。

重写是指子类用自己的方法替换父类的方法(这本身不构成多态性)。

多态性是后期绑定,例如,基类(父类)方法被调用,但直到运行时应用程序才知道实际对象是什么——它可能是一个方法不同的子类。这是因为任何子类都可以在定义基类的地方使用。

在Java中,你可以在集合库中看到很多多态性:

int countStuff(List stuff) {
  return stuff.size();
}

List是基类,编译器不知道你计数的是链表、向量、数组还是自定义列表实现,只要它像List一样:

List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);

如果你超载了,你会:

int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...

编译器会选择countStuff()的正确版本来匹配参数。

Polymorphism is a multiple implementations of an object or you could say multiple forms of an object. lets say you have class Animals as the abstract base class and it has a method called movement() which defines the way that the animal moves. Now in reality we have different kinds of animals and they move differently as well some of them with 2 legs, others with 4 and some with no legs, etc.. To define different movement() of each animal on earth, we need to apply polymorphism. However, you need to define more classes i.e. class Dogs Cats Fish etc. Then you need to extend those classes from the base class Animals and override its method movement() with a new movement functionality based on each animal you have. You can also use Interfaces to achieve that. The keyword in here is overriding, overloading is different and is not considered as polymorphism. with overloading you can define multiple methods "with same name" but with different parameters on same object or class.

什么是多态性?

来自java教程

多态性的字典定义是指生物学中的一个原理,在这个原理中,一个有机体或物种可以有许多不同的形式或阶段。这个原则也可以应用于面向对象编程和Java语言等语言。类的子类可以定义它们自己独特的行为,同时还可以共享父类的一些相同功能。

通过对实例和定义的考虑,应采用覆盖式回答。

关于你的第二个问题:

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

它应该被称为重写。

看一下这个例子,了解不同类型的覆盖。

基类不提供实现,子类必须重写完整方法-(抽象) 基类提供默认实现,子类可以改变行为 子类通过调用super.methodName()作为第一条语句向基类实现添加扩展 基类定义了算法的结构(Template方法),子类将覆盖算法的一部分

代码片段:

import java.util.HashMap;

abstract class Game implements Runnable{

    protected boolean runGame = true;
    protected Player player1 = null;
    protected Player player2 = null;
    protected Player currentPlayer = null;

    public Game(){
        player1 = new Player("Player 1");
        player2 = new Player("Player 2");
        currentPlayer = player1;
        initializeGame();
    }

    /* Type 1: Let subclass define own implementation. Base class defines abstract method to force
        sub-classes to define implementation    
    */

    protected abstract void initializeGame();

    /* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
    protected void logTimeBetweenMoves(Player player){
        System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
    }

    /* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
        super.methodName() in first line of the child class method and specific implementation later */
    protected void logGameStatistics(){
        System.out.println("Base class: logGameStatistics:");
    }
    /* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
    protected void runGame() throws Exception{
        System.out.println("Base class: Defining the flow for Game:");  
        while ( runGame) {
            /*
            1. Set current player
            2. Get Player Move
            */
            validatePlayerMove(currentPlayer);  
            logTimeBetweenMoves(currentPlayer);
            Thread.sleep(500);
            setNextPlayer();
        }
        logGameStatistics();
    }
    /* sub-part of the template method, which define child class behaviour */
    protected abstract void validatePlayerMove(Player p);

    protected void setRunGame(boolean status){
        this.runGame = status;
    }
    public void setCurrentPlayer(Player p){
        this.currentPlayer = p;
    }
    public void setNextPlayer(){
        if ( currentPlayer == player1) {
            currentPlayer = player2;
        }else{
            currentPlayer = player1;
        }
    }
    public void run(){
        try{
            runGame();
        }catch(Exception err){
            err.printStackTrace();
        }
    }
}

class Player{
    String name;
    Player(String name){
        this.name = name;
    }
    public String getName(){
        return name;
    }
}

/* Concrete Game implementation  */
class Chess extends Game{
    public Chess(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized Chess game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate Chess move:"+p.getName());
    }
    protected void logGameStatistics(){
        super.logGameStatistics();
        System.out.println("Child class: Add Chess specific logGameStatistics:");
    }
}
class TicTacToe extends Game{
    public TicTacToe(){
        super();
    }
    public void initializeGame(){
        System.out.println("Child class: Initialized TicTacToe game");
    }
    protected void validatePlayerMove(Player p){
        System.out.println("Child class: Validate TicTacToe move:"+p.getName());
    }
}

public class Polymorphism{
    public static void main(String args[]){
        try{

            Game game = new Chess();
            Thread t1 = new Thread(game);
            t1.start();
            Thread.sleep(1000);
            game.setRunGame(false);
            Thread.sleep(1000);

            game = new TicTacToe();
            Thread t2 = new Thread(game);
            t2.start();
            Thread.sleep(1000);
            game.setRunGame(false);

        }catch(Exception err){
            err.printStackTrace();
        }       
    }
}

输出:

Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:

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

后期绑定 继承。

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

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

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

多态性简单来说就是“多种形式”。

它不需要继承来实现…作为接口实现,它根本不是继承,服务于多态需求。可以说,接口实现比继承更能满足多态需求。

例如,你会创建一个超类来描述所有会飞的东西吗?我不这么认为。你最好创建一个描述飞行的界面,然后就这样吧。

因此,由于接口描述行为,而方法名描述行为(对程序员来说),将方法重载视为一种较小形式的多态性并不过分。