Skip to content
AgileLogics
6 min read

Inheritance

Prerequisites: Constructors and shared members

Inheritance lets a class build on another: the new class (derived class) gets all the members of the base class and can add or change behavior.

Public Class Animal
    Public ReadOnly Property Name As String

    Public Sub New(name As String)
        Me.Name = name
    End Sub

    Public Overridable Function Sound() As String
        Return "..."
    End Function

    Public Function Speak() As String
        Return $"{Name} says {Sound()}"
    End Function
End Class

Public Class Dog
    Inherits Animal

    Public Sub New(name As String)
        MyBase.New(name)
    End Sub

    Public Overrides Function Sound() As String
        Return "Woof"
    End Function
End Class

Public Class Puppy
    Inherits Dog

    Public Sub New(name As String)
        MyBase.New(name)
    End Sub

    Public Overrides Function Sound() As String
        Return MyBase.Sound().ToLower() & "!"
    End Function
End Class

Module Program
    Sub Main()
        Dim animals As Animal() = {New Animal("Generic"), New Dog("Rex"), New Puppy("Bit")}
        For Each a In animals
            Console.WriteLine(a.Speak())
        Next
    End Sub
End Module
Generic says ...
Rex says Woof
Bit says woof!
  • Inherits Animal must be the first line of the class.
  • Overridable allows a method to be replaced; Overrides replaces it. (C#'s virtual and override.)
  • MyBase calls the base class — its constructor (MyBase.New) or its version of a method.
  • Speak is defined once in Animal but calls the right Sound for each object. This is polymorphism.

Abstract classes

MustInherit makes a class that can't be created directly, and MustOverride declares a method each subclass must implement:

Public MustInherit Class Shape
    Public MustOverride Function Area() As Double

    Public Function Describe() As String
        Return $"{Me.GetType().Name} with area {Area():F2}"
    End Function
End Class

Public Class Circle
    Inherits Shape
    Public Property Radius As Double
    Public Overrides Function Area() As Double
        Return Math.PI * Radius ^ 2
    End Function
End Class

Public Class Square
    Inherits Shape
    Public Property Side As Double
    Public Overrides Function Area() As Double
        Return Side * Side
    End Function
End Class

Module Program
    Sub Main()
        Dim shapes As New List(Of Shape) From {New Circle With {.Radius = 1}, New Square With {.Side = 2}}
        For Each s In shapes
            Console.WriteLine(s.Describe())
        Next
    End Sub
End Module
Circle with area 3.14
Square with area 4.00

Checking and converting types

Public Class Animal
End Class

Public Class Dog
    Inherits Animal
    Public Function Fetch() As String
        Return "fetching!"
    End Function
End Class

Module Program
    Sub Main()
        Dim a As Animal = New Dog()
        If TypeOf a Is Dog Then
            Dim d = DirectCast(a, Dog)
            Console.WriteLine(d.Fetch())
        End If

        Dim maybeDog = TryCast(New Animal(), Dog)
        Console.WriteLine(maybeDog Is Nothing)
    End Sub
End Module
fetching!
True

DirectCast converts to a derived type and throws if it's wrong; TryCast returns Nothing instead.

NotInheritable and Shadows

  • NotInheritable Class prevents inheritance (C#'s sealed).
  • NotOverridable Overrides stops further overriding in subclasses.
  • Shadows hides a base member instead of overriding it — rarely what you want; the compiler warns when you do it by accident.

Keep hierarchies shallow. When classes only need to share a capability, an interface (next lesson) is usually a better fit than a base class.