就Java而言,当有人问:
什么是多态?
将超载或重载是一个可以接受的答案?
我认为还有更多的东西.
如果您有一个抽象基类定义了一个没有实现的方法,并且您在子类中定义了该方法,那还是会覆盖吗?
我认为超载肯定不是正确的答案.
表达多态性的最清晰方式是通过抽象基类(或接口)
public abstract class Human{ ... public abstract void goPee(); }
这个类是抽象的,因为这个goPee()
方法不适用于人类.它只适用于男性和女性的子类.此外,人类是一个抽象的概念 - 你不能创造一个既不是男性也不是女性的人.它必须是一个或另一个.
所以我们通过使用抽象类来推迟实现.
public class Male extends Human{ ... @Override public void goPee(){ System.out.println("Stand Up"); } }
和
public class Female extends Human{ ... @Override public void goPee(){ System.out.println("Sit Down"); } }
现在我们可以告诉整个房间充满了人类去撒尿.
public static void main(String[] args){ ArrayListgroup = new ArrayList (); 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 ...
多态性是类实例的行为能力,就好像它是其继承树中另一个类的实例,通常是其祖先类之一.例如,在Java中,所有类都继承自Object.因此,您可以创建Object类型的变量,并为其分配任何类的实例.
一个覆盖是一种函数,它发生在一个继承自另一个类的类中.覆盖函数"替换"从基类继承的函数,但这样做的方式是,即使其类的实例假装通过多态而成为不同的类型,也会调用它.参考前面的示例,您可以定义自己的类并覆盖toString()函数.因为此函数是从Object继承的,所以如果将此类的实例复制到Object类型变量中,它仍然可用.通常,如果在假装是Object时调用类上的toString(),实际触发的toString版本就是在Object本身定义的版本.但是,因为函数是一个覆盖,所以即使在类实例中,也会使用类中toString()的定义.
重载是定义具有相同名称但具有不同参数的多个方法的操作.它与重写或多态无关.
这是伪C#/ Java中的多态性示例:
class Animal { abstract string MakeNoise (); } class Cat : Animal { string MakeNoise () { return "Meow"; } } class Dog : Animal { string MakeNoise () { return "Bark"; } } Main () { Animal animal = Zoo.GetAnimal (); Console.WriteLine (animal.MakeNoise ()); }
Main函数不知道动物的类型,并且取决于MakeNoise()方法的特定实现的行为.
编辑:看起来Brian打败了我.有趣的是我们使用相同的例子.但上面的代码应该有助于澄清这些概念.
多态性是指不止一种形式,同一对象根据需要执行不同的操作.
多态性可以通过两种方式实现,即那些方式
方法覆盖
方法重载
方法重载意味着使用相同的方法名称在同一个类中编写两个或多个方法,但传递参数不同.
方法重写意味着我们在不同的类中使用方法名称,这意味着在子类中使用父类方法.
在Java中实现多态,超类引用变量可以保存子类对象.
要实现多态性,每个开发人员必须在项目中使用相同的方法名称.
覆盖和重载都用于实现多态性.
您可以在一个或多个子类中重写的类中拥有一个方法.该方法根据用于实例化对象的类来执行不同的操作.
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); } }
你是正确的,重载不是答案.
两者都不是最重要的.覆盖是获得多态性的手段.多态性是对象根据其类型改变行为的能力.当展示多态性的对象的调用者不知道对象是什么特定类型时,这是最好的证明.
特别是说重载或覆盖不能全面展示.多态性只是一个对象根据其类型专门化其行为的能力.
我不同意这里的一些答案,因为在具有相同名称的方法可以表现不同的情况下,重载是多态(参数多态)的一种形式,给出不同的参数类型.一个很好的例子是运算符重载.您可以定义"+"以接受不同类型的参数 - 比如字符串或int - 并且基于这些类型,"+"将表现不同.
多态性还包括继承和重写方法,尽管它们可以是基本类型中的抽象或虚拟.就基于继承的多态性而言,Java仅支持单类继承,将其多态行为限制为单个基类型链的行为.Java确实支持多接口的实现,这是多态行为的另一种形式.
多态只是意味着"多种形式".
它没有要求继承来实现...因为接口实现(根本不是继承)满足多态需求.可以说,接口实现为继承提供了"更好"的多态需求.
例如,你会创建一个超类来描述所有可以飞行的东西吗?我不应该想.您最好能够创建一个描述航班的界面并将其留在那里.
因此,由于接口描述了行为,并且方法名称描述了行为(对程序员而言),因此将方法重载视为较小形式的多态性并不是一件容易的事.
经典的例子,狗和猫是动物,动物有makeNoise的方法.我可以遍历一系列动物,在它们上面调用makeNoise,并期望它们会在那里进行相应的实现.
调用代码不必知道它们是什么特定的动物.
这就是我认为的多态性.