The concept of interfaces in C#
Join the DZone community and get the full member experience.
Join For FreeInterfaces are exactly what the word means – they provide a connection layer. Basically, an interface can define the structure of a class by specifying the events methods, functions, properties and/or indexers that must be present in the class. An interface does not strictly limit the functionality of a class – there can be additional events, properties, functions, methods and/or indexers present, but those specified by the interface are mandatory. Consider it a skeleton structure for a class.
Interfaces are a great language element that is extremely useful when it comes to application extensibility. There are cases when the developer doesn’t want to expose the application code to third-party developers, who want to develop additional components for the base app. In this case, the developer exposes a set of “hooks” that can be used by other developers to connect to the application. The best analogy that comes to mind i the structure of wall sockets. You can plug a power cord in a specific socket, therefore the socket is the interface, while the plug is the actual class implementation. If the class doesn’t implement the interface, it cannot be used with the application.
Interfaces are declared by using the interface keyword. An interface cannot contain method or event implementations, but rather indicates their structure. A common practice is naming interfaces with a starting capital I, however this is not a requirement.
For example, here is a sample interface:
interface IMoveable
{
void MoveUp();
void MoveRight();
void MoveDown();
void MoveLeft();
int Location { get; set; }
}
As you see, it includes the structure outline for four methods and a property. There is no implementation, and there shouldn’t be any. For this specific example, the interface defines a class that is moveable (I am also going to use an analogy for the example). A suitable class could be MobileHouse:
public class MobileHouse : IMoveable
{
public void MoveUp()
{
Location += 1;
}
public void MoveRight()
{
Location += 1;
}
public void MoveDown()
{
Location -= 1;
}
public void MoveLeft()
{
Location -= 1;
}
private int m_Location = 0;
public int Location
{
get { return m_Location; }
set { m_Location = value; }
}
}
The class follows the exact structure specified by the interface. To specify that a class inherits an interface, the <ClassName> : <InterfaceName> declaration structure is used. The class implementation can slightly differ from the interface specification. What if the developer wants to introduce a MoveTwiceToLeft method? He can do that by adding something like this to the initial class:
public void MoveTwiceToLeft()
{
Location -= 2;
}
This
will work fine as long as the class will be instantiated directly or
the method used internally. However, if it is accessed via an interface,
this method will not be directly accessible, since the interface
doesn't offer a "hook" for it. To show an example of such a behavior, I
am going to declare the same class in two different ways.
First
of all, I am going to declare it via an interface instance:
Given that MobileHouse implements the IMoveable interface, I can see all methods and a property accesible through the interface declaration, but I have no direct access to other methods or properties present in the class.
The second way is to declare an instance of
the class directly:
I can now see class-specific methods, including the new MoveTwiceToLeft. It’s up to the developer to choose the way to call an instance of a class, however, from the extensibility compliance point of view, the first implementation is better, and here is why.
Here is a method that changes the Location property of an IMoveable instance passed to it:
void MoveObject(IMoveable unit)
{
unit.MoveDown();
unit.MoveLeft();
Debug.Print(unit.Location.ToString());
}
This specific method doesn’t know what class will be passed to it. It can be MobileHouse, or if the developer wants, later on additional classes can be added, like Car or Rocket – all these are moveable and have the same controlling methods.
In case of a direct class reference, only an instance of that specific class can be passed. The code below is totally valid:
void MoveObject(MobileHouse unit)
{
unit.MoveDown();
unit.MoveLeft();
Debug.Print(unit.Location.ToString());
}
However, it doesn’t have much room for extensibility, since other class types cannot be passed to it, and separate methods have to be implemented for the specific instances.
A class can also implement multiple interfaces. For example, here is an IForLiving sample interface, showing that the object is suitable for living in it:
interface IForLiving
{
int Size { get; set; }
uint MonthlyCost { get; set; }
}
I added the needed properties to the MobileHouse class as well:
private int m_size = 0;
public int Size
{
get { return m_size; }
set { m_size = value; }
}
private uint m_monthlyCost = 0;
public uint MonthlyCost
{
get { return m_monthlyCost; }
set { m_monthlyCost = value; }
}
But
this is not enough – I actually need to show that the class implements
the new interface, so my class declaration should look like that to
correct this:
public class MobileHouse : IMoveable, IForLiving
A comma separates the multiple interfaces that are being implemented in a specific class.
Interfaces can also inherit the structure of other interfaces. For example, I am going to modify my interfaces just like this:
interface IForLiving
{
int Size { get; set; }
uint MonthlyCost { get; set; }
}
interface IMoveable : IForLiving
{
void MoveUp();
void MoveRight();
void MoveDown();
void MoveLeft();
int Location { get; set; }
}
In this case, for my MobileHouse class I can only show that it implements the IMoveable interface, however, the Size and MonthlyCost properties will still be required, since the IMoveable interface inherits IForLiving.
Opinions expressed by DZone contributors are their own.
Comments