Understanding OO Essentials: Classes, Inheritance, Polymorphism and Interfaces, Page 4
I think the best way to demonstrate what an interface is and how it can work for you is to start off with an example. Suppose the company you work for is progressively minded (I hope that's not too big of a stretch for you!) and that they'd like for all their employees receive at least 10 days of training a year. They want to add the ability to track this to their systems, but in addition to tracking training for both salaried and hourly employees, they also want to track training of contractors.
Both SalariedEmployee and HourlyEmployee are children of Employee, but Contractor is not. And there's no easy way to reengineer the system so that it could be. So, unfortunately, polymorphism isn't an option here. What other options are there?
When you have a situation where you have common functionality across a number of very different classes and there's no close, common parent object that would make polymorphism work, the best option is usually an interface. This can happen often when you don't have multiple inheritance, because you are always limited to one and only one parent for your class.
Here's what an interface definition might look like for the training tracking system.
Interface TrainingTracking Sub AddTrainingDays(ByVal Num As Integer) Function GetTriainingDaysTotal() As IntegerEnd Interface
An interface is a description of some of the members available from a class. In practice, the syntax typically looks similar to a class definition, except that there's no code defined for the methods — just their name, the arguments passed and the type of the value returned.
So what good is it? None by itself. But you create an interface so that classes will implement it. Here's the Contractor class.
Class ContractorImplements TrainingTrackingPrivate TrainingDays As IntegerPublic Name As StringPublic Phone As StringPublic Sub AddTrainingDays(ByVal Num As Integer) _ Implements TrainingTracking.AddTrainingDays TrainingDays = TrainingDays + NumEnd SubPublic Function GetTriainingDaysTotal() As Integer _ Implements TrainingTracking.GetTriainingDaysTotal Return TrainingDaysEnd FunctionEnd Class
In this example, Contractor does not have an Inherits clause and does not inherit from anything. But in the real world, it probably would, which would prevent it from inheriting from Employee.
However you'll notice that it does have another clause that looks similar: Implements. Implements is always followed by the names of one or more interfaces. Notice that although a class can only have one class that it inherits from, it can have any number of interfaces that it implements.
But what does it mean to implement an interface. The interface acts as a contract or promise. If a class implements an interface, then it must have the properties and methods of the interface defined in the class. This is enforced by the compiler.
Of course the person writing the class can choose to implement the methods however he wants, but the name, arguments and return type of each method must be identical to the definition in the interface.
In this case, the two methods, one to add days to the training for the contractor and one to retrieve the total are both implemented as they should be. In addition, in Visual Basic .NET, it is necessary to indicate to the compiler which interface method this method is designed to implement by using the Implements keyword again in the subroutine/function definition. The same is true for the other Employee classes of this system.
Class SalariedEmployeeInherits EmployeeImplements TrainingTrackingPrivate TrainingDays As Integer...Public Sub AddTrainingDays(ByVal Num As Integer) _ Implements TrainingTracking.AddTrainingDays TrainingDays = TrainingDays + NumEnd SubPublic Function GetTriainingDaysTotal() As Integer _ Implements TrainingTracking.GetTriainingDaysTotal Return TrainingDaysEnd FunctionEnd ClassClass HourlyEmployeeInherits EmployeeImplements TrainingTracking...Public Sub AddTrainingDays(ByVal Num As Integer) _ Implements TrainingTracking.AddTrainingDays TrainingDays = TrainingDays + NumEnd SubPublic Function GetTriainingDaysTotal() As Integer _ Implements TrainingTracking.GetTriainingDaysTotal Return TrainingDaysEnd FunctionEnd Class
So you can use interfaces as a way to standardize certain common functionality across many classes. By doing this you assure that classes that have similar functionality implement it in the same way. Of course, the interface doesn't make any guarantees about how a given class will implement the methods of the interface, but it does give you a clear idea of what methods are available and how to call them.
But the best part of interfaces is putting them to use. It works just like polymorphism! Suppose for example, that when employees or contractors joined the company, they were put through a three-day new employee seminar. These three days count toward their training, so you create a new subroutine that can easily be called whenever a new employee has completed the seminar.
Sub TrackNewEmployeeSeminar(ByVal Person As TrainingTracking) Person.AddTrainingDays(3)End Sub
The thing to notice here is that the argument passed in to the subroutine is of type TrainingTracking, the name of the interface. But you can't instantiate an interface! What does this mean? As you might suspect, this means that an object is being passed that implements the TrainingTracking interface. When you use this object, you can't make any more assumptions about it than that. But you can be sure that the members defined in the interface are available.
So, in this case, the AddTrainingDays method is called with an argument indicating the training lasted three days.
Here's code which calls this subroutine.
TrackNewEmployeeSeminar(Emp1)TrackNewEmployeeSeminar(Emp2)MsgBox("Emp1 Training:" & Emp1.GetTriainingDaysTotal)MsgBox("Emp2 Training:" & Emp2.GetTriainingDaysTotal)
It doesn't matter if the object passed is a SalariedEmployee, an HourlyEmployee or a Contractor. We know it will have the AddTrainingDays because we know it implements the TrainingTracking interface. If you try to send an object that doesn't implement that interface, you'll receive an error.
About the Author
Bill Hatfield is a trainer, consultant, and the author of ASP.NET for Dummies, among other books.
# # #