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).