多态 - 覆盖和重载

时间:2012-07-23 16:09:57

标签: asp.net vb.net

为什么重载称为编译时多态性并覆盖调用的运行时多态?例如,看看下面的代码:

Public Class Animal
    Public Overridable Overloads Sub Eat()
        MsgBox("Animal Eat no arguement")
    End Sub
    Public Overridable Sub Drink()
        MsgBox("Animal drink arguement")
    End Sub
End Class

Public Class Horse
    Inherits Animal
    Public Overloads Overrides Sub Eat()
        MsgBox("Horse Eat no arguement")
    End Sub
    Public Overloads Sub Eat(ByVal food As String)
        MsgBox("Horse Eat food arguement")
    End Sub
    Public Overloads Overrides Sub Drink()
        MsgBox("Animal drink arguement")
    End Sub
End Class

Public Class Form1

    Private Sub Form2_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        Dim a1 As New Animal
        Dim a2 As Animal
        a2 = New Horse
        a1.Eat()
        a2.Eat("Fruit") 'line 6
    End Sub
End Class

第6行将导致编译时错误,因为程序代表。但是,如果我向动物类添加一个Eat(String),那么它将编译。这背后的原因是什么?

以下文章中的答案还说:“Overloads关键字是可选的,但如果您将其用于一种方法,则必须将其用于该方法的所有重载:”http://stackoverflow.com/questions/ 1173257 /过载-关键字在-VB-净。如果有问题的函数也覆盖,我并不总是发现这种情况。是这种情况吗?

我正在查看一个使用接口的多态性的大型程序。我提供了上面的课程作为例子用于举例说明。

2 个答案:

答案 0 :(得分:1)

  

第6行将导致编译时错误,因为程序代表。然而,   如果我向动物类添加一个Eat(String),那么它将编译。什么   是背后的原因吗?

这是因为Animal类型公开的签名没有带字符串的Eat版本,直到您修改了基类(Animal)签名。多态性允许您将马称为动物类型,但仅通过动物的签名(除非您将其转换为马类型)。所以,如果你有另一种类型的Cat,它继承自Animal,但没有吃(""),如果VB允许你提到的那样,那将导致编译错误。

  

以下帖子中的答案也是:" Overloads关键字是   可选,但如果您将其用于一种方法,则必须将其用于所有方法   该方法的重载

我认为覆盖提供了您找到的解决方法,但并非100%确定。我个人根本不使用Overload来节省打字,因为C#没有使用它。

答案 1 :(得分:0)

我不知道他们为什么称它为编译时或运行时多态,但我会尝试解释它是如何工作的:

覆盖类成员将替换基类中该成员的实现。这意味着您无法覆盖其自己的类中的成员。

编译:

Public Class Animal
    Public Overridable Sub Eat()
        ' eat whatever
    End Sub
    Public Overrides Sub Eat()
        ' eat whatever
    End Sub
End Class

编译:

Public Class Animal
    Public Overridable Sub Eat()
        ' eat whatever
    End Sub
End Class

Public Class Horse : Inherits Animal
    Public Overrides Sub Eat()
        ' eat whatever, except meat
    End Sub
End Class

在这个例子中,我用一种不允许马吃肉的实现替换了原始实现。即使Horse类型未指定此限制,这也会禁用Animal的所有实例进食肉类产品。但是,要指定自己的食物类型,必须添加一个带有字符串参数的重载。

重载成员允许您选择原始实现或重载实现。您可以重载同一个类中的成员,也可以重载从该基类继承的子类。或者甚至在两个班级中。

这有效:

Public Class Animal
    Public Overloads Sub Eat()
        ' eat whatever
    End Sub
    Public Overloads Sub Eat(food as String)
        ' eat food
    End Sub
End Class

这也有效:

Public Class Animal
    Public Overloads Sub Eat()
        ' eat whatever
    End Sub
End Class

Public Class Horse : Inherits Animal
    Public Overloads Sub Eat(food as String)
        ' eat food
    End Sub
End Class

<强>结论

通过覆盖成员,您可以有效地禁用基本类型的实现。通过重载成员,您可以添加其他实现,因此可以使用任一实现。您只能覆盖一次成员,但可以根据需要多次重载。

<强>疑难杂症

如果您创建类型为Horse的实例,但将其分配给类型为Animal的变量,则只有基类上的成员可见,但它们仍然使用{{1}上的实现。 1}}类型。要解决此问题,请将Horse类型的实例强制转换为Animal类型。