Interfaces in C#


Interface

An interface is a contract. If you are defining an interface, then you are describing set of rules. A class can follow the rules specified by the interface. When a class fulfills the contract or rules specified by the interface, we could say that a class implements the interface.

You can define the interface like below:

public interface <interface name>
{
          //Specify the Contract
}

A simple interface [ INokiaOld ]

Let us assume there is an interface from Old cell phone model from Nokia. The interface can be:

public interface INokiaOld
{
          void SendSMS();
          void HoldCall();
}

The above code specifies a contract for old Nokia mobile phones; that is, all the phone class that implements INokiaOld should implement the function SendSMS and HoldCall. It does not matter how it will be implemented. Say for HoldCall() , some Phone can implement Hold the call for 15 Seconds and Disconnect or some other phone can implement hold the call for 60 Seconds and give a beep for every five seconds. The contract says "If a phone adhere to INokiaOld, it should able to send an SMS and it should provide the facility to hold the call.

Implementing an Interface [ INokiaOld ]

Below is the class which implements the INokiaOld interface:

//002: Class that implements the Contract
class MyNokiaOldPhone : INokiaOld
{
          //002_1: A Non Contract Function
          public void somefunction1()
          {
                   Console.WriteLine("Some Function 1");
          }
          //002_2: Contract Function 1
          public void SendSMS()
          {
                   Console.WriteLine("SMS Sent");
          }
          //002_2: Contract Function 2
          public void HoldCall()
          {
                   Console.WriteLine("Call Temporarily on Hold");
          }
}

Note that it supports some other functionality like somefunction1().  What is important is as it implements the interface INokiaOld it is giving the implementation for 1)SendSMS and 2)HoldCall.

In the client perspective, given the contract name it is guaranteed that what are the functionality it can expect from the class object and make use of it. Below is the usage of the INokiaOld:

//Usgae 001: Use a Simple Interface
MyNokiaOldPhone phone = new MyNokiaOldPhone();
phone.SendSMS();
phone.somefunction1();

//Usage 002: Only interface functions can be accessed by iface.
INokiaOld iface = phone;
iface.SendSMS();

From the above code Usage001 is nothing to do with interface. It just see phone as normal class object. But, when we look at usage002, following points are revealed:
  1. The interface type iface is pointing to the MyNokiaOldPhone object.
  2. iface is guaranteed to have access to the functionality contracted through INokiaOld.
  3. As iface is INokiaOld type , it cannot have access to somefunction1(). Yeah, somefunction1() is not contracted one.
Extending an interface [ INokiaNew ]

Below is the syntax for extending an interface from the existing one. It is quite similar to class inheritance. INokiaNew interface is created to support a new function of Sending MMS with additional to basing feature supported by the old interface. The interface is shown below:

//003: Extended Interface
public interface INokiaNew: INokiaOld
{
          void SendMMS_AVI();
}

When a Class implements this new Interface INokiaNew, it should give basic functionality expected by INokiaOld plus Sending the MMS in AVI format expected by INokiaNew.

Below is the class :

//004: Class that implements the Extended Contract
class MyNokiaNewPhone : INokiaNew
{
          //004_1: A Non Contract Function
          public void somefunction1()
          {
                   Console.WriteLine("Some Function 1");
          }
          //004_2: Base Contract Function 1
          public void SendSMS()
          {
                   Console.WriteLine("SMS Sent");
          }
          //004_3: Base Contract Function 2
          public void HoldCall()
          {
                   Console.WriteLine("Call Temporarily on Hold");
          }
          //004_4: Extended Contract Function 3
          public void SendMMS_AVI()
          {
                   Console.WriteLine("MMS Sent in AVI Format");
          }
}

Have a look at the usage of the new extended interface:

//Usage 003:
MyNokiaNewPhone phone2 = new MyNokiaNewPhone();
INokiaOld iface_basic = phone2;
INokiaNew iface_delux = phone2;
iface_basic.SendSMS(); //You can not send MMS as it is a basic interface
iface_delux.SendSMS(); //You Can access basic functionality
iface_delux.SendMMS_AVI(); //You can access extended functionality also

Note that, iface_basic can only access the functionality of the basic interface, which is nothing but Sending an SMS and Holding the call. But, though iface_delux you access all the three functionality; that is two basic (SMS, Call Hold) and one extended (MMS).

Implementing More than One Interface [INokiaNew, ISamSung ]

Let Us Assume that below is the ISamSung interface contract:

//005: A New Samsung Interface
public interface ISamSung
{
          void SendMMS_Mpeg();
          // Commented the Below Function as per Balaji's reply.
          // void PlayMusic();
}

Now the HyBridPhone class is going to have basic functionality given by Nokia Old and advanced feature given by Samsung. For this we can implement both ISamSung  and INokiaOld interfaces. Below is the Class that Implements both the Interfaces:

//006: Class implementing both the inteface
class HybridPhone : INokiaOld, ISamSung
{
          //006_1: Contract for Nokia
          public void SendSMS()
          {
                   Console.WriteLine("SMS Sent");
          }
          //006_2: Contract Nokia
          public void HoldCall()
          {
                   Console.WriteLine("Call Temporarily on Hold");
          }
          //006_3: Contract Samsung
          public void SendMMS_Mpeg()
          {
                   Console.WriteLine("MMS Sent in MPeg format");
          }
}

The client code now can access the Samsung functionality as well as basic Nokia functionality from the Class object HybridPhone. Below is the code which will demonstrate this:

HybridPhone phone3 = new HybridPhone();
//004_1: Use Nokia Interface
INokiaOld iface_nokia = phone3;
iface_nokia.SendSMS();
//004_2: Use Samsung inteface
ISamSung iface_samsung = phone3;
iface_samsung.SendMMS_Mpeg();

Note that how the inteface functionality is extracted from the same phone object using different interfaces type. You can not  get the Samsung functionality through INokiaOld interface and Basic Nokia functionality through SamSung interface.

Casting the Interface - Is versus As

Look at the below code:

HybridPhone phone3 = new HybridPhone();
INokiaOld iface_nokia = phone3;
//005_1: Check the Type using is keyword
if (iface_nokia is ISamSung)
{
          //005_2: Cast it to the other interface type
          ISamSung iface_samsung1 = (ISamSung) iface_nokia;
          iface_samsung1.SendMMS_Mpeg();
}

In the above code, first we are checking iface_nokia is ISamSung type. The first look will get you to give the answer NO. But, note that, here if you read it like "Does the object pointed by the interface type INokiaOld is ISamSung as well". You do say Yes now. Look at how (005_2) casting the object pointed by iface_nokia is done to ISamSung. Once the Casting is done, you can access the functionality of Samsung.

//005_3: Cast and Assign
ISamSung iface_samsung2 = iface_nokia as ISamSung;
iface_samsung2.SendMMS_Mpeg();

If you look at the above code the 'As' keyword also does the same job. When Object is not ISamSung we will get NULL assigned to iface_samsung2.

Up Next
    Ebook Download
    View all
    Learn
    View all