Introduction To Interfaces
I recommend you complete the Introduction to Classes before doing this as I will be continuing with the code from it.
If you would like to keep the previous code for reference then I would suggest you copy the entire folder and use that. If not then open the Solution you were using for the Introduction to Classes.
Interfaces are fairly simple and this tutorial will be much shorter the the class one. First off what is an interface? Well I mentioned that a Class is like the blueprint of an Object and an Interface is like the blueprint of a Class. Although not necessary an interface can be used to define the methods and properties a class has. The class is not limited to just those methods and properties set by the interface and a class can have many interfaces as well as other methods and properties of it's own. Best of all interfaces have to code!!! That's right there is no code in an interface. Just declarations of the necessary properties and methods.
Since an interface is just to define the properties and methods they are all public and don't have to be declared as public. I will continue with the ShapeClass and start by adding a new Class and call it IFourSidedShape. I have yet to find an Add Interface item so you will have to change Class to Interface.
Public Interface IFourSidedShape End Interface
Now lets think of characteristics of a four sided shape. What comes to mind? Square, Rectangle, Parallelogram, Rhombus, Trapezoid. OK not all those would normally come to mind and you may not even know what some of those are. That doesn't matter the only thing that matters is they all have four sides but do we need to keep track of all four sides? No. A square and rhombus have four sides but they are all the same length and a rectangle and parallelogram have two pairs of sides. So they all have sides but the number of sides you need to keep track of differ. This sounds like a parameter list to me even if some will only have one value. Since the number of different sides is well, different, there should be a property to tell how many different sides there are. This should be a read only property because the Shape determines the number of different sides not the user so they have no need to change it. Along with the Area and Perimeter functions we have a simple Interface.
Public Interface IFourSidedShape
Property Sides(ByVal Index As Integer) As Double
ReadOnly Property DifferentSides() As Integer
Function Area() As Double
Function Perimeter() As Double
End Interface
That's all there is to Interfaces. Well not exactly, you probably want to know how to use them. So lets start by adding a new Class and calling it Rectangle. To use an interface you "Implement" it with the keyword Implements on the line after Public Class ClassName.
Public Class Rectangle
Implements IFourSidedShape
End Class
Notice the picture next to the IFourSidedShape in Intellisense and see that it differs from a Class picture since it is an Interface. As soon as you do that you will see the squiggly line under IFourSidedShape and in the Task List you will see the four errors saying the Property Sides, ReadOnly Property DifferentSides, Function Area, and Function Perimeter are not implemented. This is because all methods and properties of the Interface must be implemented in order for it to be validly implemented. So declare the properties and methods.
Public Property Sides(ByVal Index As Integer) As Double
Get
End Get
Set(ByVal Value As Double)
End Set
End Property
Public ReadOnly Property DifferentSides() As Integer
Get
End Get
End Property
Public Function Area() As Double
End Function
Public Function Perimeter() As Double
End Function
It still has those errors even though I declared all the necessary properties and methods! Yep that's right. Kind of a neat feature (but sometimes annoying) is the fact that the name in the class doesn't have to be the same as it is in the interface. So you must declare that it implements the corresponding method or property in the interface again with the Implements keyword.
Public Property Sides(ByVal Index As Integer) As Double _
Implements IFourSidedShape.Sides
Get
End Get
Set(ByVal Value As Double)
End Set
End Property
Public ReadOnly Property DifferentSides() As Integer _
Implements IFourSidedShape.DifferentSides
Get
End Get
End Property
Public Function Area() As Double Implements IFourSidedShape.Area
End Function
Public Function Perimeter() As Double _
Implements IFourSidedShape.Perimeter
End Function
There now all the errors should be gone. As I mentioned the Interface is the blueprint of a class and it has no code. That means the Class has all the code. A rectangle has two different sides (length and width) so we will need a two element array and DifferentSides will return 2. The Area is length * width and the perimeter is length * 2 + width * 2. Also to show that you are not limited to just those set by the interface there will also be the IsSquare function which will compare the two sides and if they are equal will return True. If not return False.
Your code should end up something like:
Public Class Rectangle
Implements IFourSidedShape
Private mdblSides(2) As Double
Public Property Sides(ByVal Index As Integer) As Double _
Implements IFourSidedShape.Sides
Get
If Index > -1 And Index < 2 Then
Return mdblSides(Index)
Else
Return 0
End If
End Get
Set(ByVal Value As Double)
If Index > -1 And Index < 2 And Value > 0 Then
mdblSides(Index) = Value
End If
End Set
End Property
Public ReadOnly Property DifferentSides() As Integer _
Implements IFourSidedShape.DifferentSides
Get
Return 2
End Get
End Property
Public Function Area() As Double Implements IFourSidedShape.Area
Return mdblSides(0) * mdblSides(1)
End Function
Public Function IsSquare() As Boolean
If mdblSides(0) = mdblSides(1) Then
Return True
Else
Return False
End If
End Function
Public Function Perimeter() As Double _
Implements IFourSidedShape.Perimeter
Return mdblSides(0) * 2 + mdblSides(1) * 2
End Function
End Class
Now do the same for the Square. If you want you can create an new class (call is Square2) or just change the existing one. There aren't many differences between the Square class and Rectangle class. The Square class only has one different side so it will have an array of one and DifferentSides will return 1. Also the is no need for the IsSquare function and the Area and Perimeter have a slight change in math.
Public Class Square2
Implements IFourSidedShape
Private mdblSides(1) As Double
Public Property Sides(ByVal Index As Integer) As Double _
Implements IFourSidedShape.Sides
Get
If Index = 0 Then
Return mdblSides(Index)
Else
Return 0
End If
End Get
Set(ByVal Value As Double)
If Index = 0 And Value > 0 Then
mdblSides(Index) = Value
End If
End Set
End Property
Public ReadOnly Property DifferentSides() As Integer _
Implements IFourSidedShape.DifferentSides
Get
Return 1
End Get
End Property
Public Function Area() As Double Implements IFourSidedShape.Area
Return mdblSides(0) ^ 2
End Function
Public Function Perimeter() As Double _
Implements IFourSidedShape.Perimeter
Return mdblSides(0) * 4
End Function
End Class
Now you have two classes that implement the IFourSidedShape interface. You may be wondering what the point of this is. It seams like a lot of work for nothing. Well now comes the pay off. An interface is a data type. It cannot be directly created (Dim r As New IFourSidedShape()) but classes that implement it are also consider that type. Return to the Module and inside Sub Main() declare a Rectangle variable.
Sub Main()
Dim r As New Rectangle()
If TypeOf r Is Rectangle Then
Console.WriteLine ("r is a Rectangle. That's not a surprise")
End If
If TypeOf r Is IFourSidedShape Then
Console.WriteLine ("r is a IFourSidedShape. Wow that's great!")
End If
End Sub
As the output to the Console will show "r" is a Rectangle and it is also a IFourSidedShape.
Then set both different sides of "r" to the same value and try the IsSquare function.
r.Sides(0) = 10
r.Sides(1) = 10
Console.WriteLine ("IsSquare = " & r.IsSquare())
Also a variable of the Interface type can hold objects of other classes that implement it. Declare two variables of type IFourSidedShape and set one to a new Rectangle and the other to a new Square2 (or Square if you changed it). Notice that it works the same way but also notice that the Rectangle one doesn't have the IsSquare function. This is because the data type is IFourSidedShape so it has the methods and properties of that and doesn't know what the actual object it holds is. If you are sure the variable is a certain type then you can convert it to get to that Type's methods and properties.
Dim f1 As IFourSidedShape
Dim f2 As IFourSidedShape
f1 = New Rectangle()
f2 = New Square2()
f1.Sides(0) = 10
f1.Sides(1) = 10
f2.Sides(0) = 3
Console.WriteLine ("Rectangle Area = " & f1.Area() & " Square Area = " & f2.Area())
' this line is invalid
'Console.WriteLine("IsSquare = " & f1.IsSquare())
' to make it valid you must cast it
Console.WriteLine ("IsSquare = " & CType(f1, Rectangle).IsSquare())
' if f1 wasn't a Rectangle then CType would throw an InvalidCastException
Some final notes are you can't declare the constructors (Public Sub New()) inside an interface. The class can still have multiple constructors (ie like we did with Square and Triangle) but those can't be defined within the interface. If you want to implement multiple interfaces then separate them with commas.
Public Class Rectangle
Implements IFourSidedShape, IAnotherClass, IYetAnotherClass
Congratulations you have completed the Introduction to Interfaces. You can now either proceed with the Class & Interface Example which will be an ongoing example throughout these tutorials or continue on with the Introduction to Inheritance tutorial.
Author Information:
http://www.programmers-corner.com
