A tutorial on interfaces in C#

Get here : http://www.codeproject.com/KB/cs/cs_interfaces.aspx

Introduction

Interfaces in C # provide a way to achieve runtime polymorphism. Using interfaces we can invoke functions from different classes through the same Interface reference, whereas using virtual functions we can invoke functions from different classes in the same inheritance hierarchy through the same reference. Before things start getting difficult let me start using simple and short examples to explain the concept of interfaces. Here's a short example that shows you what an interface looks like.

P1.cs

 Collapse
class Demo
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
  }
}

interface abc
{  
}

Output

 Collapse
Hello Interfaces

The above program compiles and runs successfully to produce the desired output. The above program consists of a class Demo and within it an entry point function Main() that prints Hello Interfaces. The above program also defines an interface abc. Interface abc is empty at this point of time. Let's add some elements to this interface.

P2.cs

 Collapse
class Demo
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
  }
}

interface abc
{
  int x;  
}

Output

 Collapse
P2.cs(11,3): error CS0525: Interfaces cannot contain fields

Error! Interfaces in C# cannot contain fields i.e variables. The above program declared an integer variable x in the interface abc. And that's what hit the C# compiler badly.

P3.cs

 Collapse
class Demo
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
  }
}

interface abc
{
  void xyz()
  {
     System.Console.WriteLine("In xyz");
  }  
}

Output

 Collapse
P3.cs(11,8): error CS0531: 'abc.xyz()': interface members cannot have a 
    definition

This time over we included a function xyz() inside the interface found that this too hurt the C# compiler. It told us loudly that interface members cannot have a defination. Does this mean that if we just have a function declaration inside the interface abc that is fine with the C# compiler? Let's find it out.

P4.cs

 Collapse
class Demo
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
  }
}

interface abc
{
  void xyz();
}

Output

 Collapse
Hello Interfaces

The above program compiles and runs successfully to produce the desired output. Finally we made the compiler happy. Interfaces in C# can only contain function declarations. Now let us see interfaces in action.

Interfaces are contracts that a class implements in its own way. This means an interface will contain function prototypes and a class that marries this interface will have to take the responsibility of defining the functions whose prototypes are declared by the marrying interface.

So its time to perform the marriage between our groom class Demo and the bride interface abc.

P4.cs

 Collapse
class Demo : abc
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
  }
}

interface abc
{
  void xyz();
}

Output

 Collapse
P4.cs(1,7): error CS0535: 'Demo' does not implement interface member 
    'abc.xyz()'
P4.cs(11,8): (Location of symbol related to previous error)

Well, in the above program class Demo did marry the interface abc through the line class demo : abc but as usual there's a small misunderstanding between the newlyweds. Class Demo needs to take the responsibility of defining the functions whose prototypes are declared by the marrying interface abc. Since class Demo in the above program has not been implemented i.e. defined the function xyz whose prototype is declared by the marrying interface abc we get an error in the above program. To fix this issue, the class Demo has to take the responsiility of defining the function xyzwhose prototype is declared by the marrying interface abc. And that is what you get to see in the following program.

P5.cs

 Collapse
class Demo : abc
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
  }

  void xyz()
  {
     System.Console.WriteLine("In xyz");
  }  
}

interface abc
{
  void xyz();
}

Output

 Collapse
a.cs(1,7): error CS0536: 'Demo' does not implement interface member 
    'abc.xyz()'.'Demo.xyz()' is either static, not public, 
    or has  the wrong return type.
a.cs(16,8): (Location of symbol related to previous error)
a.cs(7,8): (Location of symbol related to previous error)

Error again! It's not enough for the class Demo to implement the function xyz. It has to impress the bride interface abc by declaring its implementation ofxyz as public. And that's what is done by the following program.

P6.cs

 Collapse
class Demo : abc
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    xyz();
  }

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

interface abc
{
  void xyz();
}

Output

 Collapse
Hello Interfaces
In xyz

Bingo! The above program compiles and runs successfully to produce the desired output. As mentioned earlier using interfaces we can invoke functions from different classes using the same interface reference. For this, we need to have different classes to implement the same interface. In the above program our class Demo is implementing the interface abc. Let's have another classSample that implements the interface abc.

P7.cs

 Collapse
class Demo : abc
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    refDemo.xyz();
    Sample refSample = new Sample();
    refSample.xyz();    
  }

  public void xyz()
  {
     System.Console.WriteLine("In Demo :: xyz");
  }  
}

interface abc
{
  void xyz();
}

class Sample : abc
{
  public void xyz()
  {
     System.Console.WriteLine("In Sample :: xyz");
  }  
}

Output

 Collapse
In Demo :: xyz
In Sample :: xyz

The above program compiles and runs successfully to produce the desired output. refDemo is a reference to the object of class Demo. refSample is a reference to the object of class Sample. Both the classes implement the interface abc and hence define their own implementation of the functionxyz(). From within the entry point function Main() xyz() of the respective classes Demo and Sample are invoked through references refDemo andrefSample.

Now that we have two different classes implementing the same interface its time to show you how to invoke functions from different classes using the same interface reference.

P8.cs

 Collapse
class Demo : abc
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    abc refabc = new Demo();
    refabc.xyz();
    abc refabc = new Sample();
    refabc.xyz();    
  }

  public void xyz()
  {
     System.Console.WriteLine("In Demo :: xyz");
  }  
}

interface abc
{
  void xyz();
}

class Sample : abc
{
  public void xyz()
  {
     System.Console.WriteLine("In Sample :: xyz");
  }  
}

Output

 Collapse
In Demo :: xyz
In Sample :: xyz

The above program compiles and runs successfully to produce the desired output. Inside Main() we have an interface reference refabc of type interface abc. Reference of object of class Demo is stored in refabc andxyz() of class Demo is invoked using refabc. Next, the reference of object of class Sample is stored in refabc and xyz() of class Sample is invoked usingrefabc. Thus, we were able to invoke xyz() that belongs to different classesDemo and Sample via a common interface reference refabc.

The following program uses a for loop to invoke the functions of different classes Demo and Sample that implement the same interface "interface abc" using a single interface reference refabc whose type matches the interface "interface abc" which the classes impliment.

P9.cs

 Collapse
class Demo : abc
{
  public static void Main()
  {
    abc [] refabc = {new Demo(), new Sample()} ;
    for (int i = 0; i<= 1; i++)
      refabc[i].xyz();
  }

  public void xyz()
  {
     System.Console.WriteLine("In Demo :: xyz");
  }  
}

interface abc
{
  void xyz();
}

class Sample : abc
{
  public void xyz()
  {
     System.Console.WriteLine("In Sample :: xyz");
  }  
}

Output

 Collapse
In Demo :: xyz
In Sample :: xyz

The above program compiles and runs successfully to produce the desired output. refabc is an array of type interface abc. It stores the references to objects of classes Demo and Sample. In the for loop, using the array refabc, we are invoking the function xyz() of class Demo and Sample. A class can impliment as many interfaces as it wants. Take the following program.

P10.cs

 Collapse
class Demo : abc, def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    abc refabc = new Demo();
    refabc.xyz();
  }

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

  public void pqr()
  {
     System.Console.WriteLine("In xyz");
  }
}

interface abc
{
  void xyz();
}

interface def
{
  void pqr();
}

Output

 Collapse
Hello Interfaces
In xyz

The above program compiles and runs successfully to produce a desired output. Class Demo implements interface abc and thereby function xyz(). Class Demo also impliments interface def and thereby function pqr(). refabc which is a variable of type Interface abc, refers to object of class Demo. Next xyz() of Demo is invoked via refabc as refabc is a variable of type Interface abc which contains the prototype for function xyz().

P11.cs

 Collapse
class Demo : abc, def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    abc refabc = new Demo();
    refabc.xyz();
    refabc.pqr();
  }

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

  public void pqr()
  {
     System.Console.WriteLine("In xyz");
  }
}

interface abc
{
  void xyz();
}

interface def
{
  void pqr();
}

Output

 Collapse
P11.cs(9,5): error CS0117: 'abc' does not contain a definition for 'pqr'

Error! An attempt to invoke pqr() of Demo via refabc fails as refabc is a variable of type Interface abc which contains the prototype for functionxyz() and NOT pqr(). One can invoke pqr() of Demo via a reference variable of type Interface def as the interface def contains the prototype for function pqr(). And that's what is done by the following program.

P12.cs

 Collapse
class Demo : abc, def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    abc refabc = refDemo;
    refabc.xyz();
    def refdef = refDemo;
    refdef.pqr();
  }

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

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

interface abc
{
  void xyz();
}

interface def
{
  void pqr();
}

Output

 Collapse
Hello Interfaces
In xyz 
In pqr

The above program compiles and runs successfully to produce a desired output. Class Demo impliments the interfaces abc and def. An object of classDemo is created and its reference is stored in refDemo. refabc which is a variable of type Interface abc, refers to the object of class Demo. Next xyz()of Demo is invoked via refabc as refabc is a variable of type Interface abcwhich contains the prototype for function xyz(). Similarly, refdef which is a variable of type Interface def, refers to object of class Demo. Next pqr() ofDemo is invoked via refdef as refdef is a variable of type Interface defwhich contains the prototype for function pqr().

P13.cs

 Collapse
class Demo : abc, def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    abc refabc = refDemo;
    refabc.xyz();
    def refdef = refDemo;
    refdef.xyz();
  }

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

interface abc
{
  void xyz();
}

interface def
{
  void xyz();
}

Output

 Collapse
Hello Interfaces
In xyz
In xyz

The above program compiles and runs successfully to produce a desired output. Both the interfaces abc and def declare the prototypes for functionxyz(). Class Demo implements interfaces abc as well as def and defines the function xyz() as well. Thus we can invoke the function xyz() through either of the interface reference variables (refabc or refdef) after storing the reference to the object of class Demo in refabc or refdef. This poses a question, how can we have an implementation of xyz that is specific to interface abc and implementation of xyz that is specific to def inside classDemo? Well, for this we need to use the fully qualified names as in the following program.

P14.cs

 Collapse
class Demo : abc, def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    abc refabc = refDemo;
    refabc.xyz();
    def refdef = refDemo;
    refdef.xyz();
  }

  public void abc.xyz()
  {
     System.Console.WriteLine("In abc.xyz");
  }  

  public void def.xyz()
  {
     System.Console.WriteLine("In def.xyz");
  }  

}

interface abc
{
  void xyz();
}

interface def
{
  void xyz();
}

Output

 Collapse
a.cs(13,15): error CS0106: The modifier 'public' is not valid for this item
a.cs(18,15): error CS0106: The modifier 'public' is not valid for this item

Bummer! We used the fully qualified name and we got an error. That's because when we use fully qualified names for functions whose prototypes are a part of interfaces, the compiler doesn't need decorators like public. So we decided to remove the access specifier public from the above program.

P15.cs

 Collapse
class Demo : abc, def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    abc refabc = refDemo;
    refabc.xyz();
    def refdef = refDemo;
    refdef.xyz();
  }

  void abc.xyz()
  {
     System.Console.WriteLine("In abc.xyz");
  }  

  void def.xyz()
  {
     System.Console.WriteLine("In def.xyz");
  }  

}

interface abc
{
  void xyz();
}

interface def
{
  void xyz();
}

Output

 Collapse
Hello Interfaces
In abc.xyz
In def.xyz

The above program compiles and runs successfully to produce a desired output. A fully qualified naming system allows us to define interfaces having same function prototypes. In the above example, interface abc and defcontain the same function prototypes for function xyz(). Class Demoimpliments both the interfaces. Using fully qualified names, it defines implementation of xyz that is specific to interface abc and implementation ofxyz that is specific to interface def.

P16.cs

 Collapse
class Demo : def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    def refdef = refDemo;
    refdef.xyz();
    refdef.pqr();
  }

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

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

}

interface abc
{
  void xyz();
}

interface def : abc
{
  void pqr();
}

Output

 Collapse
Hello Interfaces
In xyz
In pqr

The above program compiles and runs successfully to produce a desired output. Interfaces support inheritance. Interface def inherits prototypes from interface abc. Class Demo implements the interface def. Interface variablerefdef stores the reference to object of class Demo. Functions xyz() andpqr() of class Demo are invoked through interface reference variablerefdef.

What do you think of the fully qualified names of xyz() and pqr() would be after interface def inherits from interface abc.

P17.cs

 Collapse
class Demo : def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    def refdef = refDemo;
    refdef.xyz();
    refdef.pqr();
  }

  void def.xyz()
  {
     System.Console.WriteLine("In xyz");
  }  

  void def.pqr()
  {
     System.Console.WriteLine("In pqr");
  }  

}

interface abc
{
  void xyz();
}

interface def : abc
{
  void pqr();
}

Output

 Collapse
P17.cs(12,8): error CS0539: 'def.xyz' in explicit interface declaration is 
    not a member of interface
P17.cs(29,11): (Location of symbol related to previous error)
P17.cs(1,7): error CS0535: 'Demo' does not implement interface member 
    'abc.xyz()'
P17.cs(26,8): (Location of symbol related to previous error)

Bummer! The prototype of function xyz is an original member of interfaceabc. Thus, even if interface def inherits from the interface abc, the fully qualified name of the function xyz() remains as abc.xyz and not def.xyzas done in the above program. In fact, we got a compiler error. This can be fixed by using the correct fully qualified name of function xyz() as shown in the following program.

P18.cs

 Collapse
class Demo : def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    def refdef = refDemo;
    refdef.xyz();
    refdef.pqr();
  }

  void abc.xyz()
  {
     System.Console.WriteLine("In xyz");
  }  

  void def.pqr()
  {
     System.Console.WriteLine("In pqr");
  }  

}

interface abc
{
  void xyz();
}

interface def : abc
{
  void pqr();
}

Output

 Collapse
Hello Interfaces
In xyz
In pqr

The above program compiles and runs successfully to produce a desired output. But there are some pitfalls when using the fully qualified function names.

P19.cs

 Collapse
class Demo : def
{
  public static void Main()
  {
    System.Console.WriteLine("Hello Interfaces");
    Demo refDemo = new Demo();
    refDemo.xyz();
    refDemo.pqr();
  }

  void abc.xyz()
  {
     System.Console.WriteLine("In xyz");
  }  

  void def.pqr()
  {
     System.Console.WriteLine("In pqr");
  }  

}

interface abc
{
  void xyz();
}

interface def : abc
{
  void pqr();
}

Output

 Collapse
P19.cs(7,5): error CS0117: 'Demo' does not contain a definition for 'xyz'
P19.cs(8,5): error CS0117: 'Demo' does not contain a definition for 'pqr'

The above program fails to clear the compilation hurdle. refDemo refers to an object of class Demo. We are invoking xyz() using refDemo(). For C#,xyz() and ddd.xyz() are two different things. It knows that abc.xyz()exists. It also knows that just xyz() is nowhere in the class. That's why we get an error which says Class Demo does not contain a definition of xyz(). For C#, abc.xyz() can be invoked by an interface reference of type abc only. Similarly, def.pqr() can be invoked by an interface reference of type def only.

posted @ 2010-07-21 10:36  qiang.xu  阅读(414)  评论(0编辑  收藏  举报