Click here to Skip to main content
Click here to Skip to main content

Tagged as

Interfaces for Beginners-II [USING Interfaces]

, 16 Dec 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
This is part 2 of my article on interfaces for beginners. It focuses on usage of interfaces.

In the part 1 of the Article "Interfaces in C# for Beginners", I explained how interfaces work in C#. In this article, "The Usage of Interfaces", I focus on what interfaces are and how interfaces are commonly used in programs.

Warning: You need to have lot of patience to read and understand why interfaces are used. So be prepared Smile | :) .

Let's first understand the meaning of the term Interface.

Meaning of Interface:

What are eyes? They are our interface which allow us to interface with the outside world and help us interpret what we see. What are doors? They are the interfaces of a house which allow us to enter the house or go out of the house. Thus, an interface is something that connects the outside world to the inside world. The interface is located at the boundary of the system periphery that holds the interface.

There are sports matches played between two teams. When the two teams belong to different nations, matches between these two teams are referred to as "Inter-National" matches. On the same lines, Interface = Inter-Face, which means between two faces. The face of a human being provides a unique identity with which he/she can interact with the world. He/She can see the face of other people and vice versa through the eyes that are located in front on the face periphery.

I hope this helps understand the meaning of the term "Interface."

Difference between Interface and Function

Now let's understand the difference between interface and function conceptually.

Interfaces can be unidirectional or bi-directional. Ears are an example of unidirectional Interfaces. Information flows from the outside world to the inside world. The mouth is an example of a bi-directional interface. Information flows from the outside to the inside world in the form of food and drinks while information flows from the inside world to the outside world in the form of speech and unwanted food and drinks.

Thus, conceptually, the main purpose of an interface is to get information from the outside world into the system and to send the processed information from inside world to the outside world. Conceptually, the main purpose of the functions is to process the information received through the interfaces and return the processed information back to the interfaces. Thus the interfaces act as input/output sockets while the functions act as processing engines of a factory/mixer grinder.

Consider a human being, let's call him Jack. He is a healthy individual. He intakes some food through his interface called a mouth. Someone looks at this and warns Jack that the food is poisonous. This warning hits Jack's ears which act as a unidirectional interface. The warning is processed by the functions executed by parts within his ears and the meaning is interpreted as the food is not good for him. In return he spits the food out of his mouth which here acts as a bi-directional interface.

Technically speaking, conceptually, an interface is supposed to connect the outside world to the inside world of the system and an interface is located on the system periphery, whereas the Function is supposed to execute/process the information passed to it by the interface. This means, the interface will capture the information from the outside world, send it to the functions, the functions will process the information and create a meaning out of the information and accordingly create an impact in the form of a response emitted through other interfaces of the system.

Codewise, interfaces appear like functions. Hence the typical question, what is difference between an interface and a functions? Smile | :) .

Difference between directly working with objects versus working through Interface

Now to understand the difference between directly working with an objects versus working with objects through interfaces. Consider a sick patient. To cure him and heal him we feed him medicine, e.g. tablets through the interface called a "mouth." The medicine in turn reaches the affected organ and cures it. This is like working through the interfaces. Now consider that the patient is not getting cured even by medicines e.g. tablets. In such a case, the doctor conducts an operation where he/she breaks open the body and directly work on the organ to fix the issue and make it working. This is like directly working with the object and its functions. I hope this clarifies the difference between directly working with objects versus working with objects through interfaces.

It's always a good practice to have your application talk to the objects through interfaces rather than talking to the objects directly using functions. Consider the following class.

P1.cs

class Demo
{
  public static void Main()
  {
    Home h = new Home();
    h.MainDoor();
    h.WindowDoor();
  }
}

class Home
{
  public void MainDoor()
  {
     System.Console.WriteLine("MainDoor");
  }

  public void WindowDoor()
  {
     System.Console.WriteLine("WindowDoor");
  }  
}

Instead of having the functions such as MainDoor and WindowDoor in class home, we could have defined them as Interface as shown in P2.cs

P2.cs

interface Doors
{
  void MainDoor   (bool switch);
  void WindowDoor (bool switch);
}

class Demo
{
  public static void Main()
  {
    Home h = new Home();
    bool bOpen = true;
    bool bClose = false;
    Doors iDoors;
    iDoors = h;
    iDoors.MainDoor(bOpen);
    iDoors.WindowDoor(bClose);
  }
}

class Home : Doors
{
  
  public void MainDoor(bool switch)
  {
     System.Console.WriteLine("MainDoor open" + switch);
  }

  public void WindowDoor(bool switch)
  {
     System.Console.WriteLine("WindowDoor open" + switch);
  }  
}

Note that in the above program we are talking to the home object via the interface iDoors and not directly invoking MainDoor() and WindowDoor() even though it's possible.

  • h.MainDoor() is also possible.
  • iDoors.MainDoor() is also possible.
  • But the latter [iDoors.MainDoor()] is more conceptual and desired than the former [h.MainDoor()].

Using Interfaces to invoke functions from objects that belong to different classes

  • Consider class A which has got a function SortUsingQuickSortAlgorithm().
  • Consider class B which had got a dunction SortUsingBubbleSortAlgorithm().
  • Let's say we need both the algorithms in Class C. We could do this by inheriting Class C from Class A and Class B.

What is the problem here? Well not here but there can be as illustrated below.

  • Consider class O which has got a function Sort() and impliments sort algorithm using merge sort algorithm.
  • Let's say we derive class A and class B from class O.
  • Consider class A which has got a function Sort() and impliments sort algorithm using quick sort algorithm.
  • Consider class B which has got a function Sort() and impliments sort algorithm using bubble sort algorithm.
  • Let's say we need both the algorithms in Class C. We could do this by inheriting Class C from Class A and Class B.
  • But there happens a collision also known as ambiguity between sort() of class A and sort() of class B inside inheriting class C. This is avoided by having Interface as it helps to point to exact function that belongs to the class.

Thus, Common Processing Functions can also be a part of Interface. e.g. Build(), Sort(), Draw() where the implementation of build/sort()/Draw() would differ from one class to other class.

Take the following example.

P3.cs

class LivingRoom
{
  public void CloseDoor()
  {
    System.Console.WriteLine("LivingRoom");
  }
}

class Kitchen
{
  public void CloseDoor()
  {
    System.Console.WriteLine("Kitchen");
  }
}

class Bedroom 
{
  public void CloseDoor()
  {
    System.Console.WriteLine("Bedroom");
  }
}

class Balcony
{
  public void CloseDoor()
  {
    System.Console.WriteLine("Balcony");
  }
}

class App
{
  LivingRoom obj1 = new LivingRoom  ();
  Kitchen   obj2 = new Kitchen  ();
  Bedroom obj3 = new Bedroom();
  Balcony obj4 = new Balcony();

  obj1.CloseDoor();
  obj2.CloseDoor();
  obj3.CloseDoor();
  obj4.CloseDoor();
}

In the above example we are directly working with the objects and its functions which are supposed to be interfaces because CloseDoor() is not transforming any Data.

CloseDoor() appears to be an operation on an interface like Door which connects the outside world to inside world and vice versa. The rectified program looks as follows.

P4.cs

Interface iDoor
{
  void CloseDoor();
}

class LivingRoom: iDoor
{
  public void CloseDoor()
  {
    System.Console.WriteLine("LivingRoom");
  }
}

class Kitchen: iDoor
{
  public void CloseDoor()
  {
    System.Console.WriteLine("Kitchen");
  }
}

class Bedroom : iDoor
{
  public void CloseDoor()
  {
    System.Console.WriteLine("Bedroom");
  }
}

class Balcony: iDoor
{
  public void CloseDoor()
  {
    System.Console.WriteLine("Balcony");
  }
}

class App
{
  LivingRoom obj1 = new LivingRoom  ();
  Kitchen    obj2 = new Kitchen  ();
  Bedroom    obj3 = new Bedroom();
  Balcony    obj4 = new Balcony();
  iDoor iCloseDoor[] = {obj1, obj2, obj3, obj4};
  
  //Invoking methods of different classes in one go.
  for (int i=0;i<4;i++)
    iCloseDoor[i].CloseDoor();

}

Now in the above example using the interface iDoor, we are able to access the CloseDoor() function present in any object belonging to different classes. An array of Interface can contain any objects belonging to any class that implements the interface.

Some Ideas of using the Interfaces

We can make use of interfaces for implementing multiple bill payment strategies. Let's say you want to be able to purchase a product and pay bill by Cash or by Credit card or by debit card, you can go for the use of interfaces as shown in the following example.

P5.cs

Interface Cashier
{
  int payByCash(int amount);
  int payByCreditCard(int cardNumber, int amount);
  int payByDevitCard(int cardNumber, int amount);
}

class Shoes : Cashier
{

  public int payByCash(int amount){/* Implimentation for pay by cash */};
  public int payByCreditCard(int cardNumber, int amount){/* Implimentation for pay by credit card */};
  public int payByDevitCard(int cardNumber, int amount) {/* Implimentation for pay by Debit card */};
}

class Shirts : Cashier
{
  public int payByCash(int amount){/* Implimentation for pay by cash */};
  public int payByCreditCard(int cardNumber, int amount){/* Implimentation for pay by credit card */};
  public int payByDevitCard(int cardNumber, int amount) {/* Implimentation for pay by Debit card */};
}

class ClientApp
{
  public static void main()
  {
    Shoes s1   = new Shoes();
    Shoes s2   = new Shoes();
    Shoes s3   = new Shoes();
    Shirts sh1 = new Shirts();
    Shirts sh2 = new Shirts();
    Shirts sh3 = new Shirts();

    Cashier Jack;

    Jack = s1; Jack.payByCash(1000);
    Jack = s2; Jack.payByCreditCard(123456,1000);
    Jack = s3; Jack.payByDebitCard(7891011,1000);

    
    Jack = sh1; Jack.payByCash(1000);
    Jack = sh2; Jack.payByCreditCard(123456,1000);
    Jack = sh3; Jack.payByDebitCard(7891011,1000);
  }
}

We created an interface called as cashier because every product will come to client finally only through the cashier once we have made the payments. So we will have three method prototypes in Interface Cashier viz payByCash, pyByDebitCard, and payByCreditCard. Next we have two classes viz Shoes and Shirt that impliment the Interface Cashier. The code for these functions is kind of similar in both the classes. Next, inside the ClientApp, we create the objects of Shirt and Shoes and purchase them through Interface Cashier named as Jack.  

There is lot of redundancy in this example because the code for payByCash, pyByDebitCard, and payByCreditCard functions is kindof similar in both the classes

There is redundancy and maintenance. A change to one of the functions in one class had to be followed by similar change in the other class.  

To avoid this we thought of using the interfaces in a different way as below.

P6.cs

Interface ClientsPaymentStrategy
{
  int pay(int cardnumber, int amount);
}

class PayByCash : ClientsPaymentStrategy
{
  public int pay(int cardNumber, int amount) {/* Implimentation for pay by cash...ignore card number here */};
}

class PayByCreditCard : ClientsPaymentStrategy
{
  public int pay(int cardNumber, int amount)  {/* Implimentation for pay by credit card */};
}

class PayByDebitCard : ClientsPaymentStrategy
{
  public int pay(int cardNumber, int amount)  {/* Implimentation for pay by debit card */};
}


interface Cashier
{
  int makePayment();
}

class Shoes : Cashier
{
  ClientsPaymentstrategy p;
  int Price;

  Shirts ()
  {
     Price = 1000;
     cardnumber = 0;
     p = new PayByCash();
  }

  public SetPaymentMethod( int cardNumber, ClientsPaymentstrategy c) 
  {
    p = c;
    this.cardnumber = cardnumber;
  }

  public int makePayment()
  {
    p.pay(cardNumber, Price)
  };
}



class Shirts : Cashier
{
  ClientsPaymentstrategy p;
  int Price;
  int cardNumber;

  Shirts ()
  {
    Price = 2000; 
    cardNumber = 0;
    p = new PayByCash();
  }

  public SetPaymentMethod( int cardNumber, ClientsPaymentstrategy c) 
  {
    p = c;
    this.cardnumber = cardnumber;
  }
  
  public int makePayment()
  {
    p.pay(cardNumber, Price);
  };
}

class Client
{
  int cardNumber;
  public static void main()
  {
    Shoes s1   = new Shoes();
    Shoes s2   = new Shoes();
    Shoes s3   = new Shoes();
    Shirts sh1 = new Shirts();
    Shirts sh2 = new Shirts();
    Shirts sh3 = new Shirts();

    purchaseProduct(s1);
    purchaseProduct(s2);

    s3.setPaymentMethod(cardnumber, new PayByDebitCard() );
    purchaseProduct(s3);

    purchaseProduct(sh1);
    purchaseProduct(sh2);

    sh3.setPaymentMethod( cardnumber, new PayByCreditCard() );
    purchaseProduct(sh3);

  }

  private void purchaseProduct(Cashier Jack)
  {
     Jack.makePayment();
  }
}

In the above program we have defined one interface called as ClientsPaymentStrategy which has a prototype called pay(). This interface is implemented by Concrete classes called PayByCash, PayByCreditCard and PayByDebitCard. Next we have Interface Cashier with one method prototype called makePayment(). This interface is implemented by classes Shirt and Shoes. Inside the Class Shirt and Shoes we have their respective prices defined. Each class has a setPaymentMethod() which sets the payment method by passing the object of concrete classes defined above. By default the payment method is set to payByCash.

Inside the client App we are creating Shoes and Shirt Objects, and purchasing them through Cashier Jack using the make payment method which routs the call to respective functions PayByCash, PayByCreditCard and PayByDebitCard.

Thus interfaces are used to achieve LOOSE COUPLING and avoiding CODE REDUNDANCY very effectively. I hope this article was helpful for you.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Chetan Kudalkar
Software Developer (Senior)
India India
I am a Software engineer with around 7+ years of experience. Most of my experience is in Storage technology.

Comments and Discussions

 
SuggestionTYPO PinmemberMember 1101851217-Aug-14 23:15 
QuestionHere is another practical example: PinprofessionalDietmar Schoder2-Aug-14 11:26 
GeneralMy vote of 5 PinmemberMember 105126108-Jan-14 20:15 
GeneralMy vote of 5 PinmemberKapil SIPL24-Dec-13 3:55 
GeneralRe: My vote of 5 PinmemberChetan Kudalkar25-Dec-13 22:33 
GeneralSyntax PingroupJohn Bracey16-Dec-13 23:10 
GeneralRe: Syntax PinmemberChetan Kudalkar16-Dec-13 23:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150327.1 | Last Updated 16 Dec 2013
Article Copyright 2013 by Chetan Kudalkar
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid