在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:
没有:
重载是指使用相同的函数名,但接受不同的参数。
重写是指子类用自己的方法替换父类的方法(这本身不构成多态性)。
多态性是后期绑定,例如,基类(父类)方法被调用,但直到运行时应用程序才知道实际对象是什么——它可能是一个方法不同的子类。这是因为任何子类都可以在定义基类的地方使用。
在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()的正确版本来匹配参数。
重写和重载都用于实现多态性。
你可以在一个类中有一个方法 它在或中被覆盖 更多的子类。这个方法可以 不同的东西取决于哪个 类用于实例化对象。
abstract class Beverage {
boolean isAcceptableTemperature();
}
class Coffee extends Beverage {
boolean isAcceptableTemperature() {
return temperature > 70;
}
}
class Wine extends Beverage {
boolean isAcceptableTemperature() {
return temperature < 10;
}
}
你也可以有一种方法 用两组或多组参数重载。这个方法可以 不同的东西基于 传递的参数类型。
class Server {
public void pour (Coffee liquid) {
new Cup().fillToTopWith(liquid);
}
public void pour (Wine liquid) {
new WineGlass().fillHalfwayWith(liquid);
}
public void pour (Lemonade liquid, boolean ice) {
Glass glass = new Glass();
if (ice) {
glass.fillToTopWith(new Ice());
}
glass.fillToTopWith(liquid);
}
}
多态性就其意义而言更有可能……java中的override
这都是关于同一个对象在不同情况下的不同行为(在编程方式中…你可以调用不同的参数)
我认为下面的例子会帮助你理解……虽然它不是纯java代码…
public void See(Friend)
{
System.out.println("Talk");
}
但是如果我们改变参数…行为将会改变…
public void See(Enemy)
{
System.out.println("Run");
}
人(这里的“对象”)是一样的……
重写更像是通过声明一个与上层方法(超级方法)具有相同名称和签名的方法来隐藏一个继承的方法,这为类添加了多态行为。 换句话说,选择要调用的级别方法的决定将在运行时而不是在编译时做出。 这就引出了接口和实现的概念。