如果要高效使用面向对象编程或OOP,多态性非常有用。
假设你拥有一个动物园。在这个动物园里面(显然)有一些动物。如果你想将它们全部存储在一个数组或列表中,你将不得不为它们使用base type,在这种情况下为Animal
。现在,从我们的基类型Animal
派生的类共享相同的属性,因此也是相同的方法。
class Animal
{
public string Shout()
{
return "I am an animal!";
}
}
现在让我们声明一个狮子的类。
class Lion : Animal
{
}
即使我们没有写Lion
类中的方法Shout
的Lion
将也实例必须提供给他们Shout
方法,因为它们从Animal
类派生。
但是,如果我们想要Lion
类到Shout
有什么不同?我们可以利用关键字virtual
和override
。这些可用于属性和方法。 virtual
表示方法或财产可以被覆盖,而override
执行实际覆盖。两者都需要被设置为正确的地方。
要覆盖我们的Shout
方法,我们必须首先将其标记为virtual
。现在
public virtual string Shout() { ... }
,我们Lion
类,我们可以在Shout
方法执行覆盖。
public override string Shout()
{
return "Rooooaaar, I am a lion!";
}
现在我们澄清了这一点,让我们来看看它的一些用法。
Lion lion1 = new Lion();
这通过调用类的构造函数创建Lion
类的新实例。如果我们现在拨打lion1.Shout()
,我们会得到"Rooooaaar, I am a lion!"
作为返回值。
Animal animal1 = new Lion();
这也适用!由于我们的Lion
类来自基类型Animal
,因此该对象可以存储在Animal
类型的对象内。但不要被愚弄!如果我们现在拨打animal1.Shout()
,我们仍然会返回"Rooooaaar, I am a lion!"
。
Animal animal2 = new Animal();
这仅仅是基类的实例,这意味着方法animal2.Shout()
将返回"I am an animal!"
。
现在,让我们说,我们有一些更多的动物,Cat
,Dog
和Lion
。不使用多态性,我们不能将它们存储在单个数组中,因为它们没有共同之处!但是,如果他们从Animal
类派生,我们可以做这样的事情:
List<Animal> animals = new List<Animal>();
animals.Add(new Cat());
animals.Add(new Dog());
animals.Add(new Lion());
animals.Add(new Animal());
所有这些上述将工作完全正常!
最后,如果你想要从这个Animal
列表中的元素,你想调用它的一些Dog
特异性方法,你可以(如果它实际上是一个Dog
对象,当然)使用animals[1] as Dog
将其转换为一个Dog
对象。但是,如果它不是Dog
对象,则只需从as
运算符得到null
。
我想,这在技术上是正确的,但并没有提供关于抽象如何与编程相关的很好的解释,也没有提供关于实际流程在代码形式或抽象的“业务示例”中看起来像什么的任何细节'形式。 – TylerH