Interfaces are considered invariant. This simply means that after you publish an interface you are not supposed to change it. Suppose we had published the IDrawable interface from the last section and then decided that we wanted to change the interface. The solution to this problem is to use interface inheritance.
To indicate that a new interface is derived from an existing interface, we must use the Inherits statement (similar to deriving a new class). Continuing our example, then, we could define a new interface, IDrawable2 , and indicate that it is derived from IDrawable . The code for the new interface would begin as shown below.
Public Interface IDrawable2 Inherits IDrawable End Interface
So far IDrawable2 has the same member as our original IDrawable interface: one method member named Draw . We can now add to IDrawable2 new members identical to the ones we discussed in the latter part of the last section. Here is the completed IDrawable2 interface.
Public Interface IDrawable2 Inherits IDrawable Property Size() As Size Property Location() As Point Event OnDraw As PaintEventHandler End Interface
The contract now states that classes that implement IDrawable2 must provide an implementation for the Draw method, the Size and Location properties, and the OnDraw event. Combining all the elements, Listing 2.7 demonstrates a Shape class that implements the IDrawable2 interface.
Listing 2.7 Implementing the IDrawable2 Interface
Public Class Shape Implements IDrawable2 Private FSize As Size Private FLocation As Point Public Property Size() As Size Implements IDrawable2.Size Get Return FSize End Get Set(ByVal Value As Size) FSize = Value End Set End Property Public Property Location() As Point Implements IDrawable2.Location Get Return FLocation End Get Set(ByVal Value As Point) FLocation = Value End Set End Property Public Sub Draw(ByVal G As Graphics) _ Implements IDrawable2.Draw G.DrawEllipse(Pens.Red, GetRect()) DoDraw(G) End Sub Public Event OnDraw As PaintEventHandler _ Implements IDrawable2.OnDraw Private Function GetRect() As Rectangle Return New Rectangle(FLocation.X, FLocation.Y, _ FSize.Width, FSize.Height) End Function Private Sub DoDraw(ByVal G As Graphics) RaiseEvent OnDraw(Me, New PaintEventArgs(G, GetRect())) End Sub End Class
You have seen all these elements before. Listing 2.7 puts them together in a complete class. You can test the code in the InterfaceDemo.sln solution.