With a VB.NET Interface we create a contract. Each class
in a VB.NET program that implements the interface
must have certain functions.
Using abstraction, we call those Functions through an Interface reference. The exact type of an Object is no longer needed. More code is shared. A program becomes simpler.
This program declares an IValue
Interface, which requires one method (Render). The Content and Image classes both implement IValue
.
IValue.Render
in different ways. The Implements keyword is used.Dictionary
is created and three String
keys are added. They point to two Image class
instances and one Content instance.TryGetValue
function is invoked twice. When the IValue
is retrieved from the Dictionary
, the Render sub is called.Interface IValue Sub Render() End Interface Class Content : Implements IValue Public Sub Render() Implements IValue.Render Console.WriteLine("Content.Render") End Sub End Class Class Image : Implements IValue Public Sub Render() Implements IValue.Render Console.WriteLine("Image.Render") End Sub End Class Module Module1 Sub Main() ' Create dictionary of Interface type instances. Dim dict As Dictionary(Of String, IValue) = New Dictionary(Of String, IValue) dict.Add("cat1.png", New Image()) dict.Add("image1.png", New Image()) dict.Add("home.html", New Content()) ' Get value from Dictionary and call their Render methods. Dim value As IValue = Nothing If dict.TryGetValue("cat1.png", value) Then value.Render() End If ' Again. If dict.TryGetValue("home.html", value) Then value.Render() End If End Sub End ModuleImage.Render Content.Render
An Interface can specify a Property. On implementing classes, all aspects of the Property (like ReadOnly
, WriteOnly
) must be preserved.
Size
property from the IWidget
interface
. We can set, and read, Size
from an IWidget
reference.Interface IWidget Property Size As Integer End Interface Class Widget Implements IWidget ''' <summary> ''' Size property implementation. ''' </summary> Property Size As Integer Implements IWidget.Size End Class Module Module1 Sub Main() ' Use Size Property on Interface. Dim w As IWidget = New Widget w.Size = 10 Console.WriteLine(w.Size) End Sub End Module10
IEnumerable
Many interfaces exist in the .NET Framework, but IEnumerable
is an important one. It is implemented by classes that provide "enumeration" over elements, in a For-Each
loop.
DisplaySize
, to handle both arrays and Lists.interface
, we avoid duplicating our code for each type (array, List
). This makes programs easier to maintain.Module Module1 Sub Main() ' Use String array as IEnumerable. Dim values() As String = {"cat", "dog", "mouse"} DisplaySize(values) ' Use List of Strings as IEnumerable. Dim valuesList As List(Of String) = New List(Of String) valuesList.Add("cat") DisplaySize(valuesList) End Sub Sub DisplaySize(ByVal col As IEnumerable(Of String)) ' Display count from interface. Console.WriteLine(col.Count()) End Sub End Module3 1
interface
We test the speed of an Interface Function call versus a Class
Function call. An Interface causes a small slowdown. Using a direct method call is faster.
IWidget
Interface. We call it through an Interface reference.Class
Function. It is specified directly on the Widget class
.GetName
is slower. GetNameDirect
is faster.Interface IWidget Function GetName(ByVal size As Integer) As String End Interface Class Widget Implements IWidget Public Function GetName(size As Integer) As String Implements IWidget.GetName ' An interface method. If size = 0 Then Return "Zero" End If Return "Unknown" End Function Public Function GetNameDirect(size As Integer) As String ' A class method. If size = 0 Then Return "Zero" End If Return "Unknown" End Function End Class Module Module1 Sub Main() Dim widget As Widget = New Widget Dim widget2 As IWidget = widget Dim m As Integer = 100000000 ' Version 1: use Interface method. Dim s1 As Stopwatch = Stopwatch.StartNew For i As Integer = 0 To m - 1 widget2.GetName(i) Next s1.Stop() ' Version 2: use Class method. Dim s2 As Stopwatch = Stopwatch.StartNew For i As Integer = 0 To m - 1 widget.GetNameDirect(i) Next s2.Stop() Dim u As Integer = 1000000 Console.WriteLine(((s1.Elapsed.TotalMilliseconds * u) / m).ToString("0.00 ns")) Console.WriteLine(((s2.Elapsed.TotalMilliseconds * u) / m).ToString("0.00 ns")) End Sub End Module3.82 ns, GetName (Interface Function) 0.95 ns, GetNameDirect (no Interface)
IComparable
With IComparable
, we indicate how two objects of a type are ordered. We tell which one comes before the other. An Integer indicates the objects relative sizes.
The .NET Framework includes many interfaces: it extensively uses them itself. Often developers use these interfaces more than custom ones.
Interfaces introduce a level of abstraction. We implement an Interface in many Classes. And then we can use those classes through that Interface.
We call the Interface functions. These in turn invoke the specialized functions from the Classes. With complexity we simplify.