6.6 Implementing interfaces


Interfaces, though new to C++ developers, is already a well-used and well- understood concept in the Java world. The idea of interfaces in C# is the same as for Java, except for the minor differences described below.

To implement one or more interfaces, use the following syntax when declaring your class:

 class <class_name>:<interface1>[,<interface2>,<interface3>...] 

Like Java

  • C# does not support multiple class inheritance, but it does allow a class to implement multiple interfaces. [11]

    [11] We can say that both Java and C# support multiple interface inheritance, but only single implementation inheritance. Though it can be confusing to use the term 'inheriting an interface' instead of 'implementing an interface', both terms are technically correct and interchangeable.

  • A C# interface can extend another C# interface.

  • You use the keyword interface to define an interface, much as you define a class. The code which follows shows an example of how to write a class which implements an interface. ISpeedBehavior [12] is an interface which contains an abstract method called TopSpeed() which returns an int . Two classes, Car and Van , implement the ISpeedBehavior interface and override TopSpeed() to provide the code body.

    [12] By convention, interface names are prefixed with an 'I' in C#. This is not mandatory, but highly recommended.

     1: using System;  2:  3:  interface ISpeedBehavior  {  4:   int TopSpeed();  5: }  6:  7:  class Car:ISpeedBehavior  {  8:   public int TopSpeed(){  9:     return 200; 10:  } 11: } 12: 13:  class Van:ISpeedBehavior  { 14:   public int TopSpeed(){ 15:     return 80; 16:   } 17: } 18: 19: class TestClass{ 20:   public static void Main(){ 21:     Car c = new Car(); 22:     Console.WriteLine(c.TopSpeed()); 23:     Van v = new Van(); 24:     Console.WriteLine(v.TopSpeed()); 25:   } 26: } 
  • All methods in an interface are implicitly public and abstract.

  • If a class implements certain interfaces, it must override to provide concrete implementations for all the abstract methods in the interfaces. Otherwise the class has to be declared as an abstract class.

  • You can use an interface object type variable to refer to an object which implemented that interface. In the code example above, since ' Car is a ISpeedBehavior ' and a ' Van is a ISpeedBehavior ' the following assignment works:

     ISpeedBehavior temp = new Car(); 

Unlike Java

  • There is no keyword for extending from a superclass (such as the extends keyword in Java), or an interface (such as the implements keyword in Java). Instead, you place the name of the interface(s) after the colon and the superclass name. If you have more than one interface, separate the interface names using commas.

  • There is a significant difference between C# and Java interfaces “ C# interfaces cannot contain fields (including C# constants and read-only fields). In Java, you can declare variables (which are implicitly public static and final) in interfaces, but not for C#. Declaring a field in a C# interface will result in a compilation error.

  • Most Java naming conventions (including Sun Microsystem's official recommendations) do not require that interfaces be named with an ' I ' in front. C# encourages (but does not mandate ) that interfaces be named with an ' I ' prefix (for example, I prefer to name an interface ISerializable instead of Serializable ).

  • Although methods in an interface are implicitly public and abstract, you cannot declare a method definition in an interface with either the public or abstract keywords in C# (doing so will result in a compilation error). On the other hand, Java allows you to declare methods inside an interface using the public or abstract modifiers, although that is superfluous.

Additional notes

  • If your class is to extend a superclass, and implement one or more interfaces, the name of the superclass must be the first after the colon in the class definition. In the next code example, replacing

     1: public class Child:Parent,I1,I2 

    with

     1: public class Child:I1,Parent,I2 

    results in a compilation error. Otherwise, the order of the interfaces in the list does not matter. If the Child class directly extends System.Object , but implements I1 and I2 , the declaration statement Child:I1,I2 will be just fine “ there is no need to explicitly extend System.Object .

     1: public class Child:Parent,I1,I2{  2:   static public void Main (){  3:   }  4:   public void MustImplement1(){  5:     // code here  6:   }  7:   public void MustImplement2(){  8:     // code here  9:   } 10: } 11: 12: public class Parent{ 13: } 14: 15: public interface I1{ 16:   void MustImplement1(); 17: } 18: 19: public interface I2{ 20:   void MustImplement2(); 21: } 

    In the example above, if either method MustImplement1() or MustImplement2() is not coded in Child , there will be a compilation error.

  • C# interfaces can contain methods and the following C# members: properties, indexers, and events “ all of which are to be implemented by the non-abstract class implementing this interface. There are no such members in Java (see section 6.2).

    Here is an interface which contains a property, event, and indexer to be implemented by a class:

     1: interface IAccelerate { 2:   double IncreaseSpeed();             // method 3:   int Speed { get; }                  // get property 4:   string this [int index] {get; set;} // indexer 5:   event TestEvent Changed;            // event 6: } 

6.6.1 More about interfaces

Name hiding of interface methods is an interesting C# feature not found in Java. Do not confuse this with name hiding of normal methods which is described in section 7.11. Before describing name hiding of interface methods, the potential problem of interface name conflict resolution is first described so that you can understand how name hiding of interface methods can help prevent a potential pitfall in C#.

6.6.1.1 Interface name conflict resolution

Naming conflicts are possible in two scenarios.

  • A superclass Parent already contains a method called Method1() , and an interface ITest contains the same method definition. A subclass Child inherits from this superclass and implements the interface. The scenario is shown in Figure 6.1 as a UML class diagram:

    Figure 6.1. Child subclasses Parent and implements ITest .

    graphics/06fig01.gif

    Here are the codes which reflect this scenario:

     1: using System;  2:  3: interface ITest {  4:   void Method1();  5: }  6:  7: class Parent {  8:   public void Method1(){  9:     Console.WriteLine("running Parent.Method1"); 10:  } 11: } 12: 13: class Child: Parent, ITest{ 14:   public static void Main(){ 15:     Child c = new Child(); 16:     c.Method1(); 17:   } 18: } 

    This gives the output:

     c:\expt>test running Parent.Method1 

    The code above compiles and runs perfectly , which means that inheriting a method of the same name signature can fulfill interface inheritance. Be aware of this because this may not be what you want.

  • Two interfaces, ITest1 and ITest2 are shown in Figure 6.2. They contain the same abstract method Method1() , and a class TestClass implements both these interfaces.

    Figure 6.2. TestClass implements both ITest1 and ITest2 .

    graphics/06fig02.gif

    Here are the codes:

     1: using System;  2:  3: interface ITest1 {  4:   void Method1();  5: }  6:  7: interface ITest2 {  8:   void Method1();  9: } 10: 11: class TestClass: ITest1, ITest2{ 12: 13:   public void Method1() { 14:     Console.WriteLine("running Method1"); 15:   } 16: 17:   public static void Main(){ 18:     TestClass tc = new TestClass(); 19:     tc.Method1(); 20:   } 21: } 

    Output:

     c:\expt>test running Method1 

    The single Method1() method in TestClass has satisfactorily passed the requirements of both interfaces.

    All is fine if this is exactly what you had wanted. But what if Method1() of ITest1 and Method1() of ITest2 are meant to do different things, or exact different behavior on TestClass ? If this is the case, you may want to perform name hiding of interface methods .

6.6.1.2 Name hiding of interface methods

You can hide a method in an interface so that it is no longer 'truly public' by

  • removing the public keyword of the method when declaring the implemented method in the class; and

  • prefixing the name of the method with the interface name.

If this is done, your method will only be visible when the type of the variable referring to the object is of the interface's type. Examine the next program in which two Method1() s have been implemented in TestClass (thus fulfilling both interfaces) but they are hidden so that both cannot be invoked on an instance of type TestClass .

 1: using System;  2:  3: interface ITest1 {  4:   void Method1();  // implicitly public  5: }  6:  7: interface ITest2 {  8:   void Method1();  // implicitly public  9: } 10: 11: class TestClass: ITest1, ITest2{ 12: 13:   void  ITest1.Method1()  { // was 'public void Method1()' 14:     Console.WriteLine("running ITest1.Method1"); 15:   } 16: 17:   void  ITest2.Method1()  { 18:     Console.WriteLine("running ITest2.Method1"); 19:   } 20: 21:   public static void Main(){ 22:     TestClass tc = new TestClass(); 23:     // tc.Method1(); // will cause compilation error 24:   } 25: } 

In this case, Method1() is no longer visible to tc , because tc is of type TestClass . Invoking Method1() by tc.Method1() will cause a compilation error. Let's change Main() a bit.

 21:   public static void Main(){ 22:     TestClass tc = new TestClass(); 23:     ITest1 it1 = (ITest1)tc; 24:  it1.Method1();  // prints out 'running                            ITest2.Method1' 25:     ITest2 it2 = (ITest2)tc; 26:  it2.Method1();  // prints out 'running                            ITest2.Method1' 27:   } 

Output:

 c:\expt>test running ITest1.Method1 running ITest2.Method1 

You need to cast tc to the correct interface type ( ITest1 or ITest2 ) before you can invoke the respective implemented method.



From Java to C#. A Developers Guide
From Java to C#: A Developers Guide
ISBN: 0321136225
EAN: 2147483647
Year: 2003
Pages: 221
Authors: Heng Ngee Mok

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net