什么是多态性,它的用途是什么,如何使用它?
当前回答
让我们打个比方。对于一个特定的音乐剧本,每个演奏它的音乐家都有自己的诠释。
音乐家可以用接口抽象,音乐家所属的流派可以是一个抽象类,它定义了一些全局解释规则,每个演奏的音乐家都可以用具体类建模。
如果你是音乐作品的听众,你可以参考剧本,例如巴赫的“富加与托卡塔”,每个演奏它的音乐家都以自己的方式多态地演奏。
这只是一个可能的设计示例(在Java中):
public interface Musician {
public void play(Work work);
}
public interface Work {
public String getScript();
}
public class FugaAndToccata implements Work {
public String getScript() {
return Bach.getFugaAndToccataScript();
}
}
public class AnnHalloway implements Musician {
public void play(Work work) {
// plays in her own style, strict, disciplined
String script = work.getScript()
}
}
public class VictorBorga implements Musician {
public void play(Work work) {
// goofing while playing with superb style
String script = work.getScript()
}
}
public class Listener {
public void main(String[] args) {
Musician musician;
if (args!=null && args.length > 0 && args[0].equals("C")) {
musician = new AnnHalloway();
} else {
musician = new TerryGilliam();
}
musician.play(new FugaAndToccata());
}
其他回答
多态:
这就是面向对象编程的概念。不同对象以自己的方式响应相同消息的能力称为多态性。
多态性源于每个类都存在于自己的名称空间中。在类定义中赋值的名称与在类定义之外赋值的名称不冲突。对象数据结构中的实例变量和对象的方法都是这样:
正如C结构的字段位于受保护的名称空间中一样,因此 对象的实例变量。 方法名也受到保护。与C函数名不同, 方法名不是全局符号。其中一个方法的名称 类不能与其他类中的方法名冲突;两个 非常不同的类可以实现同名的方法。
方法名是对象接口的一部分。当发送请求对象执行某项操作的消息时,该消息命名对象应该执行的方法。因为不同的对象可以具有同名的方法,所以必须相对于接收消息的特定对象来理解消息的含义。发送给两个不同对象的相同消息可以调用两个不同的方法。
多态的主要好处是它简化了编程接口。它允许建立可以在一个又一个类中重用的约定。您不必为添加到程序中的每个新函数都发明一个新名称,而是可以重用相同的名称。编程接口可以被描述为一组抽象行为,与实现它们的类完全不同。
例子:
例1:这是一个用Python 2.x编写的简单示例。
class Animal:
def __init__(self, name): # Constructor of the class
self.name = name
def talk(self): # Abstract method, defined by convention only
raise NotImplementedError("Subclass must implement abstract method")
class Cat(Animal):
def talk(self):
return 'Meow!'
class Dog(Animal):
def talk(self):
return 'Woof! Woof!'
animals = [Cat('Missy'),
Dog('Lassie')]
for animal in animals:
print animal.name + ': ' + animal.talk()
例2:多态性在Java中使用方法重载和方法重写概念实现。
让我们以Car为例来讨论多态性。比如福特、本田、丰田、宝马、奔驰等品牌,都是汽车类型。
但每一个都有自己的高级功能和更先进的技术涉及到他们的移动行为。
现在让我们创建一个基本类型Car
Car.java
public class Car {
int price;
String name;
String color;
public void move(){
System.out.println("Basic Car move");
}
}
让我们实现Ford Car的例子。
Ford扩展Car类型以继承其所有成员(属性和方法)。
Ford.java
public class Ford extends Car{
public void move(){
System.out.println("Moving with V engine");
}
}
上面的Ford类扩展了Car类,也实现了move()方法。尽管Ford已经通过继承可以使用move方法,但Ford仍然以自己的方式实现了该方法。这称为方法重写。
Honda.java
public class Honda extends Car{
public void move(){
System.out.println("Move with i-VTEC engine");
}
}
就像Ford一样,Honda也扩展了Car类型,并以自己的方式实现了move方法。
方法重写是启用多态性的一个重要特性。使用方法重写,子类型可以更改通过继承可用的方法的工作方式。
PolymorphismExample.java
public class PolymorphismExample {
public static void main(String[] args) {
Car car = new Car();
Car f = new Ford();
Car h = new Honda();
car.move();
f.move();
h.move();
}
}
多态性示例输出:
在PolymorphismExample类的主方法中,我创建了三个对象——Car, Ford和Honda。这三个对象都是由Car类型引用的。
请注意一个重要的一点,超类类型可以引用对象的子类类型,但反之则不可能。原因是父类的所有成员都可以通过继承对子类可用,并且在编译期间,编译器会尝试评估我们正在使用的引用类型是否具有他试图访问的方法。
因此,对于多态例子中的引用car,f和h, move方法存在于car类型中。因此,编译器通过编译过程没有任何问题。
但是当涉及到运行时执行时,虚拟机调用对象上的方法,这些方法是子类型。因此,move()方法从它们各自的实现中调用。
因此,所有对象都是Car类型的,但在运行时,执行取决于调用所发生的对象。这就是所谓的多态性。
多态是指您可以将对象视为某个对象的通用版本,但当您访问它时,代码将确定它的确切类型并调用相关代码。
下面是一个c#的例子。在控制台应用程序中创建四个类:
public abstract class Vehicle
{
public abstract int Wheels;
}
public class Bicycle : Vehicle
{
public override int Wheels()
{
return 2;
}
}
public class Car : Vehicle
{
public override int Wheels()
{
return 4;
}
}
public class Truck : Vehicle
{
public override int Wheels()
{
return 18;
}
}
现在在控制台应用程序模块的Main()中创建以下内容:
public void Main()
{
List<Vehicle> vehicles = new List<Vehicle>();
vehicles.Add(new Bicycle());
vehicles.Add(new Car());
vehicles.Add(new Truck());
foreach (Vehicle v in vehicles)
{
Console.WriteLine(
string.Format("A {0} has {1} wheels.",
v.GetType().Name, v.Wheels));
}
}
在这个例子中,我们创建了一个基类Vehicle的列表,它不知道它的每个子类有多少个轮子,但是知道每个子类负责知道它有多少个轮子。
然后我们将自行车、汽车和卡车添加到列表中。
接下来,我们可以循环遍历列表中的每个Vehicle,并将它们都视为相同的,但是当我们访问每个Vehicles 'Wheels'属性时,Vehicle类将该代码的执行委托给相关的子类。
该代码被称为多态代码,因为执行的确切代码是由在运行时引用的子类决定的。
我希望这对你有所帮助。
在面向对象编程中,多态性指的是编程语言根据对象的数据类型或类对对象进行不同处理的能力。更具体地说,它是为派生类重新定义方法的能力。
多态性允许相同的例程(函数、方法)作用于不同的类型。
由于许多现有的答案将子类型与多态性混为一谈,这里有三种实现多态性的方法(包括子类型)。
参数化(泛型)多态性允许一个例程接受一个或多个类型参数,以及正常参数,并在这些类型上运行。 子类型多态性允许例程对其参数的任何子类型进行操作。 临时多态性通常使用例程重载来授予多态行为,但也可以参考其他多态性实现。
参见:
http://wiki.c2.com/?CategoryPolymorphism
https://en.wikipedia.org/wiki/Polymorphism_ (computer_science)
一般来说,它是一种使用相同或表面上相似的API来为许多不同类型的对象提供接口的能力。有多种形式:
Function overloading: defining multiple functions with the same name and different parameter types, such as sqrt(float), sqrt(double) and sqrt(complex). In most languages that allow this, the compiler will automatically select the correct one for the type of argument being passed into it, thus this is compile-time polymorphism. Virtual methods in OOP: a method of a class can have various implementations tailored to the specifics of its subclasses; each of these is said to override the implementation given in the base class. Given an object that may be of the base class or any of its subclasses, the correct implementation is selected on the fly, thus this is run-time polymorphism. Templates: a feature of some OO languages whereby a function, class, etc. can be parameterised by a type. For example, you can define a generic "list" template class, and then instantiate it as "list of integers", "list of strings", maybe even "list of lists of strings" or the like. Generally, you write the code once for a data structure of arbitrary element type, and the compiler generates versions of it for the various element types.