Inheritance, Polymorphism and Abstraction
10.1 Inheritance Keywords
Inherits Base Overridable / Overrides / NotOverridable Overrides Virtual dispatch chain MustOverride / MustInherit Abstract member/class Hide a base member (no polymorphism) Add an overload of a base member MyBase / MyClass / Me
Base, non-virtual self, current instance
10.2 Example: Polymorphic Payroll
Public MustInherit Class Employee
Public Property Name As String
Protected Sub New(name As String)
Me.Name = name
End Sub
Public MustOverride Function MonthlyPay() As Decimal
Public Overridable ReadOnly Property Title As String = "Employee"
Public Function PaySlip() As String
Return $"{Title,-12}{Name,-10}{MonthlyPay(),12:C}"
End Function
End Class
Public Class Salaried
Inherits Employee
Public Property Annual As Decimal
Public Sub New(name As String, annual As Decimal)
MyBase.New(name)
Me.Annual = annual
End Sub
Public Overrides Function MonthlyPay() As Decimal
Return Annual / 12
End Function
End Class
Public NotInheritable Class Manager
Inherits Salaried
Public Property Bonus As Decimal
Public Sub New(name As String, annual As Decimal, bonus As Decimal)
MyBase.New(name, annual)
Me.Bonus = bonus
End Sub
Public Overrides Function MonthlyPay() As Decimal
Return MyBase.MonthlyPay() + Bonus / 12
End Function
Public Overrides ReadOnly Property Title As String = "Manager"
End Class
Dim staff As New List(Of Employee) From {New Salaried("Ana",
…10.3 Casting in Hierarchies
For Each e In staff
If TypeOf e Is Manager Then Console.WriteLine($"Bonus: {DirectCast(e, Manager).Bonus}")
Dim m = TryCast(e, Manager)
Next
Dim managers = staff.OfType(Of Manager)().ToList()10.4 When Not to Inherit
Deep hierarchies are fragile ("fragile base class"). Prefer composition and interfaces. Seal classes by default when they're not designed for extension (NotInheritable).
The Liskov Substitution Principle: a subclass must be usable wherever its base class is expected (Module 41).