Interfaces
Prerequisites: Inheritance
An interface lists members that a class promises to provide, without saying how. A class can inherit from only one base class, but can implement many interfaces.
Public Interface IShape
ReadOnly Property Name As String
Function Area() As Double
End Interface
Public Class Circle
Implements IShape
Private ReadOnly radius As Double
Public Sub New(radius As Double)
Me.radius = radius
End Sub
Public ReadOnly Property Name As String Implements IShape.Name
Get
Return "circle"
End Get
End Property
Public Function Area() As Double Implements IShape.Area
Return Math.PI * radius * radius
End Function
End Class
Public Class Square
Implements IShape
Public Property Side As Double
Public ReadOnly Property Name As String Implements IShape.Name
Get
Return "square"
End Get
End Property
Public Function Area() As Double Implements IShape.Area
Return Side * Side
End Function
End Class
Module Program
Sub PrintAll(shapes As IEnumerable(Of IShape))
For Each s In shapes
Console.WriteLine($"{s.Name}: {s.Area():F2}")
Next
End Sub
Sub Main()
PrintAll({New Circle(1), New Square With {.Side = 2}})
End Sub
End Module
circle: 3.14
square: 4.00
- Interface names start with
Iby convention. - VB is explicit: each member says which interface member it implements
with
Implements IShape.Area. The class member can even have a different name. PrintAllaccepts anything that implementsIShape— it doesn't care about the concrete class.
Built-in interfaces
Implementing standard .NET interfaces plugs your classes into the
framework. IComparable(Of T) makes objects sortable:
Public Class Player
Implements IComparable(Of Player)
Public Property Name As String
Public Property Score As Integer
Public Function CompareTo(other As Player) As Integer Implements IComparable(Of Player).CompareTo
Return other.Score.CompareTo(Score) ' highest score first
End Function
End Class
Module Program
Sub Main()
Dim players As New List(Of Player) From {
New Player With {.Name = "Ada", .Score = 80},
New Player With {.Name = "Grace", .Score = 95},
New Player With {.Name = "Linus", .Score = 70}
}
players.Sort()
For Each p In players
Console.WriteLine($"{p.Name} {p.Score}")
Next
End Sub
End Module
Grace 95
Ada 80
Linus 70
Other common ones: IDisposable (release resources with Using),
IEquatable(Of T) (value equality), and IEnumerable(Of T) (work with
For Each and LINQ).
Interfaces for testable code
Depending on an interface instead of a concrete class lets you swap implementations — for example, a fake clock in tests:
Public Interface IClock
Function Now() As Date
End Interface
Public Class FixedClock
Implements IClock
Public Function Now() As Date Implements IClock.Now
Return New Date(2025, 12, 24, 18, 0, 0)
End Function
End Class
Public Class Greeter
Private ReadOnly clock As IClock
Public Sub New(clock As IClock)
Me.clock = clock
End Sub
Public Function Greet() As String
Return If(clock.Now().Hour < 12, "Good morning", "Good evening")
End Function
End Class
Module Program
Sub Main()
Console.WriteLine(New Greeter(New FixedClock()).Greet())
End Sub
End Module
Good evening
Passing dependencies in through the constructor like this is called dependency injection; ASP.NET Core and most modern .NET frameworks are built around it.