Section 3.1. Separating Interface from Implementation


3.1. Separating Interface from Implementation

In both C# and Visual Basic 2005, the reserved word interface defines a CLR reference type that can't have any implementation, can't be instantiated, and has only public members. Saying that an interface can't have implementation means that it's as if all the interface's methods and properties were abstract. Saying it can't be instantiated means the same as if the interface were an abstract class (or MustInherit in Visual Basic 2005). For example, this interface definition:

     public interface IMyInterface     {        void Method1(  );        void Method2(  );        void Method3(  );     } 

is almost equivalent to this class definition:

     public abstract class MyInterface     {        public abstract void Method1(  );        public abstract void Method2(  );        public abstract void Method3(  );     } 

In traditional object-oriented programming, you typically use an abstract class to define a service abstraction. The abstract class serves to define a set of signatures that multiple classes will implement after deriving from the abstract class. When different service providers share a common base class, they all become polymorphic with that service abstraction, and the client can potentially switch between providers with minimum changes. There are a few important differences between an abstract class and an interface:

  • An abstract class can still have implementation: it can have member variables or non-abstract methods or properties. An interface can't have implementation or member variables.

  • A .NET class can derive from only one base class, even if that base class is abstract. However, a .NET class can implement as many interfaces as required.

  • An abstract class can derive from any other class or from one or more interfaces. An interface can derive only from other interfaces.

  • An abstract class can have nonpublic (protected or private) methods and properties, even if they are all abstract. In an interface, by definition, all members are public.

  • An abstract class can have static methods and static members and can define constants. An interface can have none of those.

  • An abstract class can have constructors. An interface can't.

These differences are deliberately in place, not to restrict interfaces, but rather to provide for a formal public contract between a service provider (the classes implementing the interface) and the service consumer (the client of the classes). Disallowing any kind of implementation details in interfaces (such as method implementations, constants, static members, and constructors) enables .NET to promote loose coupling between the service providers and the client. Because there is nothing in the contract that even hints at implementation, by definition the implementation is well encapsulated behind the interface, and service providers are free to change their implementations without affecting the client. You can even say that the interface acts like a binary shield, isolating each party from the other.

Because interfaces can't be instantiated, .NET forces clients to choose a particular implementation to instantiate. Having only public members in an interface complements the contract semantics nicely: you would not want a contract with hidden clauses or "fine print." Everything the contract implies should be public and well defined. The more explicit and well defined a contract is, the less likely it is that there will be conflicts down the road regarding exactly what the class providing the service is required to do. The class implementing the interface must implement all the interface members without exception, because it has committed to providing this exact service definition. An interface can extend only other interfaces, not classes. By deriving a new interface from an existing interface, you define a new and specialized contract, and any class that implements that interface must implement all members of the base interface(s). A class can choose to implement multiple interfaces, just as a person can choose to commit to multiple contracts.

3.1.1. Interface Implementation

To implement an interface, all a class has to do is derive from it. Example 3-1 shows the class MyClass implementing the interface IMyInterface.

Example 3-1. Defining and implementing an interface
     public interface IMyInterface     {        void Method1(  );        void Method2(  );       d Method3(  );     }            public class MyClass : IMyInterface     {        public void Method1(  )        {...}         public void Method2(  )        {...}         public void Method3(  )        {...}        //other class members     } 

As trivial as Example 3-1 is, it does demonstrate a number of important points. First, interfaces have visibilityan interface can be private to its assembly (using the internal access modifier) or it can be used from outside the assembly (with the public access modifier), as in Example 3-1. Second, even though the methods the interface defines have no access modifiers, they are by definition public, and the implementing class has to declare its interface methods as public. Third, there is no need to use new or override to qualify the method redefinition in the subclass, because an interface method by its very nature can't have any implementation and therefore has nothing to override. (If you aren't familiar with the new or override keywords, see the sidebar "C# Inheritance Directives" later in this chapter.) Finally, the class must implement all the methods the interface defines, without exception. If the class is an abstract class, it can redefine the methods without providing concrete implementation.

Example 3-2 shows how to define and implement an interface in Visual Basic 2005. In Visual Basic 2005, you need to state which interface method a class method corresponds to. As long as the signature (i.e., the parameters and return value) matches, you can even use a different name for the method. In addition, because the default accessibility in Visual Basic 2005 is public, unlike in C#, adding the Public qualifier is optional.

Example 3-2. Defining and implementing an interface in Visual Basic 2005
     Public Interface IMyInterface        Sub Method1(  )        Sub Method2(  )        Sub Method3(  )   d Interface            Public Class SomeClass        Implements IMyInterface               Public Sub Method1(  ) Implements IMyInterface.Method1        ...        End Sub               Public Sub Method2(  ) Implements IMyInterface.Method2        ...        End Sub               Public Sub Method3(  ) Implements IMyInterface.Method3        ...        End Sub     End Class 

To interact with an object using an interface, all a client has to do is instantiate a concrete class that supports the interface and assign that object to an interface variable, similar to using any other base type. Using the same definitions as in Example 3-1, the client code might be:

     IMyInterface obj;     obj = new MyClass(  );     obj.Method1(  ); 

Interfaces promote loose coupling between clients and objects. When you use interfaces, there's a level of indirection between the client's code and the object implementing the interface. If the client wasn't responsible for instantiating the object, there is nothing in the client code that pertains to the object hidden behind the interface shield. There can be many possible implementations of the same interface, such as:

     public interface IMyInterface     {...}     public class MyClass : IMyInterface     {...}     public class MyOtherClass : IMyInterface     {...} 

When a client obtains an interface reference by creating an object of type MyClass, the client is actually saying to .NET "give me MyClass's interpretation of the way IMyInterface should be implemented."

Treating interfaces as binary contracts, which shields clients from changes made to the service providers, is exactly the idea behind COM interfaces, and logically, .NET interfaces have the same semantics as COM interfaces. If you are an experienced COM developer or architect, working with interfaces is probably second nature to you, and you will feel right at home with .NET interfaces.

However, unlike COM, .NET doesn't enforce separation of the interface from the implementation. For example, using the definitions in Example 3-1, the client's code can also be:

     MyClass obj;     obj = new MyClass(  );     obj.Method1(  ); 

Because of the way the server in Example 3-1 implements the interface (as public members), nothing prevents the client from programming directly against the object providing the service, instead of the interface. I believe this is because .NET tries to make component-oriented programming accessible to all developers, including those who have trouble with the more abstract concepts of interface-based programming (see the section ".NET Adherence to Component Principles" in Chapter 1). The fact that something is possible, of course, doesn't mean you should go ahead and do it. Disciplined .NET developers should always enforce the separation, to retain the benefits of interface-based programming.

3.1.2. Explicit Interface Implementation

The way of implementing an interface shown in the previous section is called implicit interface implementation, because a public method with a name and signature that match those of an interface method is implicitly assumed to be an implementation of that interface method.

Example 3-3 demonstrates a simple technique that allows server developers to enforce the separation of the interface from the implementation. The server implementing the interface can actually prevent clients from accessing the interface methods directly by using explicit interface implementation. Implementing an interface explicitly means qualifying each interface member name with the name of the interface that defines it.

Example 3-3. Explicitly implementing an interface
     public interface IMyInterface     {        void Method1(  );        void Method2(  );     }     public class MyClass : IMyInterface     {        void IMyInterface.Method1(  )        {...}         void IMyInterface.Method2(  )        {...}        //Other methods and members     } 

Note that the interface members must be implicitly defined as private at the class's scope; you can't use any explicit access modifiers on them, including private. The only way clients can invoke the methods of explicitly implemented interfaces is by accessing them via the interface:

     IMyInterface obj;     obj = new MyClass(  );     obj.Method1(  ); 

To explicitly implement an interface in Visual Basic 2005, you need to explicitly set the method access to Private, as in Example 3-4.

Example 3-4. Explicitly implementing an interface in Visual Basic 2005
     Public Interface IMyInterface        Sub Method1(  )        Sub Method2(  )   d Interface            Public Class SomeClass        Implements IMyInterface               Private Sub Method1(  ) Implements IMyInterface.Method1        ...        End Sub               Private Sub Method2(  ) Implements IMyInterface.Method2        ...        End Sub     End Class 

You should avoid mixing and matching explicit and implicit interface implementations, as in the following fragment:

     //Avoid mixing and matching:     public interface IMyInterface     {        void Method1(  );        void Method2(  );     }     public class MyClass : IMyInterface     {        void IMyInterface.Method1(  )        {...}         public void Method2(  )        {...}        //Other methods and members     } 

Although .NET lets you mix and match implementation methods, for consistency, you should avoid it. Such mix and match forces the client to adjust its references depending on whether a particular method is accessible via an interface or directly via the object.

Assemblies with Interfaces Only

Because interfaces can be implemented by multiple components, it's good practice to put them in a separate assembly from that of the implementing components. Maintaining a separate assembly that contains only interfaces allows concurrent development of the server and the client, once the two parties have agreed on the interfaces. Such assemblies also extend the separation of interface from implementation to the code-packaging units.




Programming. NET Components
Programming .NET Components, 2nd Edition
ISBN: 0596102070
EAN: 2147483647
Year: 2003
Pages: 145
Authors: Juval Lowy

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