在Java中,当有人问:
什么是多态性?
重载或重写是可以接受的答案吗?
我认为事情远不止如此。
如果你有一个抽象基类,它定义了一个没有实现的方法,并且你在子类中定义了这个方法,这仍然是覆盖的吗?
我认为超负荷肯定不是正确的答案。
在Java中,当有人问:
什么是多态性?
重载或重写是可以接受的答案吗?
我认为事情远不止如此。
如果你有一个抽象基类,它定义了一个没有实现的方法,并且你在子类中定义了这个方法,这仍然是覆盖的吗?
我认为超负荷肯定不是正确的答案。
当前回答
什么是多态性?
来自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:
其他回答
具体地说重载或重写并没有给出全貌。多态性就是对象根据其类型专门化其行为的能力。
我不同意这里的一些答案,因为重载是一种多态形式(参数多态),在这种情况下,具有相同名称的方法可以具有不同的行为,给出不同的参数类型。一个很好的例子是操作符重载。您可以定义“+”来接受不同类型的参数——例如字符串或int型——并且基于这些类型,“+”将具有不同的行为。
多态性还包括继承和重写方法,尽管它们在基类型中可以是抽象的或虚拟的。在基于继承的多态性方面,Java只支持单个类继承,将其多态行为限制为单个基类型链。Java支持多个接口的实现,这是另一种形式的多态行为。
多态性是一个对象以多种形式出现的能力。这涉及到使用继承和虚函数来构建可交换的对象族。基类包含虚函数的原型,这些原型可能未实现,也可能具有应用程序指定的默认实现,而各种派生类都以不同的方式实现它们,以影响不同的行为。
没有:
重载是指使用相同的函数名,但接受不同的参数。
重写是指子类用自己的方法替换父类的方法(这本身不构成多态性)。
多态性是后期绑定,例如,基类(父类)方法被调用,但直到运行时应用程序才知道实际对象是什么——它可能是一个方法不同的子类。这是因为任何子类都可以在定义基类的地方使用。
在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.
多态性涉及到一种语言通过使用单一接口统一处理不同对象的能力;因此,它与覆盖有关,因此接口(或基类)是多态的,实现者是覆盖的对象(同一奖章的两个面)
无论如何,这两个术语之间的区别可以用其他语言更好地解释,比如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