多态的实际例子

61

请问有人能给我一个关于多态性的真实生活、实际应用的例子吗?我的教授总是讲那些我已经听过很多遍的关于+运算符的老套话,比如a+b = c2+2 = 4,说这就是多态性。但我真的无法将自己与这样的定义联系起来,因为我在很多书中读过并反复阅读过。

我需要的是一个带有代码的真实世界的例子,这样我才能真正地理解它。

例如,以下是一个小例子,以防您想要扩展它。

>>> class Person(object):
    def __init__(self, name):
        self.name = name

>>> class Student(Person):
    def __init__(self, name, age):
        super(Student, self).__init__(name)
        self.age = age

你是在特指操作符多态性(也称为运算符重载),还是泛型多态性? - Matthew Flaschen
多态性的概念。 - Maxx
3个回答

168

查看维基百科的示例:它在高层次上非常有帮助:

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'),
           Cat('Mr. Mistoffelees'),
           Dog('Lassie')]

for animal in animals:
    print animal.name + ': ' + animal.talk()

# prints the following:
#
# Missy: Meow!
# Mr. Mistoffelees: Meow!
# Lassie: Woof! Woof!
注意以下内容:所有动物都“说话”,但它们说的方式各不相同。因此,“说话”行为在多态性方面是多态的,具体取决于动物实现的方式。因此,“抽象”动物概念实际上并没有“说话”,但特定的动物(例如狗和猫)具有“说话”行为的具体实现。
类似地,“加”操作在许多数学实体中都已定义,但在特定情况下,您根据特定规则进行“加法”:1 + 1 = 2,但是(1 + 2i)+(2-9i)=(3-7i)。
多态行为允许您在“抽象”级别上指定常见方法,并在特定实例中实现它们。
对于您的示例:
class Person(object):
    def pay_bill(self):
        raise NotImplementedError

class Millionare(Person):
    def pay_bill(self):
        print "Here you go! Keep the change!"

class GradStudent(Person):
    def pay_bill(self):
        print "Can I owe you ten bucks or do the dishes?"

你看,百万富翁和研究生都是人。但是当涉及到支付账单时,他们具体的“支付账单”行为是不同的。


2
在一个抽象方法中引发 NotImplementedError 会破坏 super - aaronasterling
1
这与继承有何不同,子类在父类中覆盖方法? - Pyderman
3
继承是实现多态的一种方式 - Escualo
9
多态在静态语言中更有意义,因为你不能在一个数组中拥有不同类型的元素。Python允许列表包含不同类型,例如 [Cat(), Dog()],而在Java中,你必须定义这些不同的动物实例作为动物类型,将它们放入动物数组中,并遍历它来调用talk()方法。我不确定多态在Python中有什么帮助? - ThriceGood
2
你忘记在你的pay_bill方法中写self参数了! - user4813927

12

Python中一个常见的实例是类文件对象。除了实际的文件外,还有其他几种类型,包括StringIOBytesIO,它们都是类文件对象。因为它们支持所需方法(例如readwrite),所以对于像文件一样的对象,可以使用相同的方法来操作它们。


6

上面答案中的多态性的C++示例如下:

class Animal {
public:
  Animal(const std::string& name) : name_(name) {}
  virtual ~Animal() {}

  virtual std::string talk() = 0;
  std::string name_;
};

class Dog : public Animal {
public:
  virtual std::string talk() { return "woof!"; }
};  

class Cat : public Animal {
public:
  virtual std::string talk() { return "meow!"; }
};  

void main() {

  Cat c("Miffy");
  Dog d("Spot");

  // This shows typical inheritance and basic polymorphism, as the objects are typed by definition and cannot change types at runtime. 
  printf("%s says %s\n", c.name_.c_str(), c.talk().c_str());
  printf("%s says %s\n", d.name_.c_str(), d.talk().c_str());

  Animal* c2 = new Cat("Miffy"); // polymorph this animal pointer into a cat!
  Animal* d2 = new Dog("Spot");  // or a dog!

  // This shows full polymorphism as the types are only known at runtime,
  //   and the execution of the "talk" function has to be determined by
  //   the runtime type, not by the type definition, and can actually change 
  //   depending on runtime factors (user choice, for example).
  printf("%s says %s\n", c2->name_.c_str(), c2->talk().c_str());
  printf("%s says %s\n", d2->name_.c_str(), d2->talk().c_str());

  // This will not compile as Animal cannot be instanced with an undefined function
  Animal c;
  Animal* c = new Animal("amby");

  // This is fine, however
  Animal* a;  // hasn't been polymorphed yet, so okay.

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接