3

为什么重载称为编译时多态,而重载称为运行时多态?例如,看看下面的代码:

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/overloads -vb-net 中的关键字。如果有问题的功能也覆盖,我并不总是发现这种情况。是这样吗?

我正在查看一个使用多态性和接口的大型程序。出于说明目的,我提供了上面的类作为示例。

4

2 回答 2

1

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

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

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

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

于 2012-07-23T16:18:24.877 回答
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

结论

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

明白了

如果创建 type 的实例Horse,但将其分配给 type 的变量Animal,则只有基类上的成员可见,但它们仍使用该Horse类型上的实现。为了解决这个问题,将类型的实例强制Animal转换为Horse类型。

于 2013-01-10T15:04:03.840 回答