Previous section   Next section

8.5 Extending Interfaces

It is possible to extend an existing interface to add new methods or members, or to modify how existing members work. For example, you might extend ICompressible with a new interface, ICompressible2, which extends the original interface with a method to keep track of the bytes saved.

The following code creates a new interface named ICompressible2 that is identical to ICompressible except that it adds the method LogSavedBytes( ):

Interface ICompressible2
    Inherits ICompressible
    Sub LogSavedBytes( )
End Interface 'ICompressible2

Notice that your new interface (ICompressible2) inherits from the base interface (ICompressible). Classes can inherit only from a single class, but interfaces can inherit from more than one interface, as shown later in this chapter.

Classes are now free to implement either ICompressible or ICompressible2, depending on whether they need the additional functionality. If a class does implement ICompressible2, it must implement all the methods of both ICompressible2 and also ICompressible. Objects of that type can be cast either to ICompressible2 or to ICompressible.

In Example 8-4, you'll extend ICompressible to create ICompressible2. You'll then cast the Document first to be of type IStorable, then to be of type ICompressible2. Finally, you'll cast the Document object to ICompressible. This last cast is safe because any object that implements ICompressible2 must also have implemented ICompressible (the former is a superset of the latter). This is the same logic that says you can cast any object of a derived type to an object of a base type (that is, if Student derives from Human, then all Students are Human, even though not all Humans are Students).

Example 8-4. Extending interfaces
Option Strict On
Imports System
Namespace InterfaceDemo
    
    Interface IStorable
        Sub Read( )
        Sub Write(ByVal obj As Object)

        Property Status( ) As Integer
    End Interface 'IStorable
    
    ' the Compressible interface is now the
    ' base for ICompressible2
    Interface ICompressible
        Sub Compress( )
        Sub Decompress( )
    End Interface 'ICompressible

    ' extend ICompressible to log the bytes saved
    Interface ICompressible2
        Inherits ICompressible
        Sub LogSavedBytes( )
    End Interface 'ICompressible2

    ' Document implements both interfaces
    Public Class Document

        Implements ICompressible2, IStorable

        ' the document constructor
        Public Sub New(s As String)
            Console.WriteLine("Creating document with: {0}", s)
        End Sub 'New

        ' implement IStorable
        Public Sub Read( ) Implements IStorable.Read
            Console.WriteLine("Implementing the Read Method for IStorable")
        End Sub 'Read

        Public Sub Write(ByVal o As Object) Implements IStorable.Write
            Console.WriteLine( _
                  "Implementing the Write Method for IStorable")
        End Sub 'Write

        Public Property Status( ) As Integer Implements IStorable.Status
            Get
                Return myStatus
            End Get
            Set(ByVal Value As Integer)
                myStatus = Value
            End Set
        End Property

        ' implement ICompressible
        Public Sub Compress( ) Implements ICompressible.Compress
            Console.WriteLine("Implementing Compress")
        End Sub 'Compress

        Public Sub Decompress( ) Implements ICompressible.Decompress
            Console.WriteLine("Implementing Decompress")
        End Sub 'Decompress

        ' implement ICompressible2
        Public Sub LogSavedBytes( ) Implements ICompressible2.LogSavedBytes
            Console.WriteLine("Implementing LogSavedBytes")
        End Sub 'LogSavedBytes

        ' hold the data for IStorable's Status property
        Private myStatus As Integer = 0

    End Class 'Document

    Class Tester

        Public Sub Run( )
            Dim doc As New Document("Test Document")

            If TypeOf doc Is IStorable Then
                Dim isDoc As IStorable = doc
                isDoc.Read( )
            Else
                Console.WriteLine("Could not cast to IStorable")
            End If

            If TypeOf doc Is ICompressible2 Then
                Dim ilDoc As ICompressible2 = doc
                Console.Write("Calling both ICompressible and ")
                Console.WriteLine("ICompressible2 methods...")
                ilDoc.Compress( )
                ilDoc.LogSavedBytes( )
            Else
                Console.WriteLine("Could not cast to ICompressible2")
            End If

            If TypeOf doc Is ICompressible Then
                Dim icDoc As ICompressible = doc
                Console.WriteLine( _
                   "Treating the object as Compressible... ")
                icDoc.Compress( )
            Else
                Console.WriteLine("Could not cast to ICompressible")
            End If
        End Sub 'Run

        Shared Sub Main( )
            Dim t As New Tester( )
            t.Run( )
        End Sub 'Main

    End Class 'Tester

End Namespace 'InterfaceDemo

Output:
Creating document with: Test Document
Implementing the Read Method for IStorable
Calling both ICompressible and ICompressible2 methods...
Implementing Compress
Implementing LogSavedBytes
Treating the object as Compressible...
Implementing Compress

Example 8-4 starts by creating the ICompressible2 interface:

Interface ICompressible2
    Inherits ICompressible
    Sub LogSavedBytes( )
End Interface 'ICompressible2

Notice that the syntax for extending an interface is the same as that for deriving from a class. This extended interface explicitly defines only one method, LogSavedBytes( ); but of course any class implementing this interface must also implement the base interface (ICompressible) and all its members.

You define the Document class to implement both IStorable and ICompressible2:

Public Class Document
    Implements ICompressible2, IStorable

You are now free to cast the Document object to IStorable, ICompressible, or to ICompressible2:

If TypeOf doc Is IStorable Then
      Dim ilDoc As IStorable = doc

If TypeOf doc Is ICompressible Then
    Dim icDoc As ICompressible = doc

If TypeOf doc Is ICompressible2 Then
    Dim ic2Doc As ICompressible2 = doc

If you take a look back at the output, you'll see that all three of these casts succeed.


  Previous section   Next section
Top