Introducing Interfaces

Beginner Topic: Why Interfaces?

Implemented interfaces are like appliances with wall plugs. The wall plug is the interface that appliances support in order to receive AC power. An appliance can use that power in countless ways, but in order to plug into a wall socket, an appliance must supply a compatible wall plug. What the appliance does with the power corresponds to how an interface implementation varies from class to class. The specification that defines a wall plug is the contract that must be supported in order for an appliance to plug into the wall plug. Similarly, an interface defines a contract that a class must support in order to gain the capability that the interface provides.

Consider the following example: An innumerable number of file compression formats are available (.zip, .7-zip, .cab, .lha, .tar, .tar.gz, .tar.bz2, .bh, .rar, .arj, .arc, .ace, .zoo, .gz, .bzip2, .xxe, .mime, .uue, and .yenc, just to name a few). If you created classes for each compression format, you could end up with different method signatures for each compression implementation and no ability for a standard calling convention across them. Although the method signature could be defined in an abstract member of a base class, deriving from a common base type uses up a class's one and only inheritance, with an unlikely chance of sharing code across the various compression implementations, thereby making the potential of a base class implementation useless.

Instead of sharing a common base class, each compression class needs to implement a common interface. Interfaces define the contract that a class supports in order to interact with the other classes that expect the interface. Although there are many potential compression algorithms, if all of them could implement the IFileCompression interface and its Compress() and Uncompress() methods, then the code for calling the algorithm on any particular compression class would simply involve a cast to the IFileCompression interface and a call into the members, regardless of which class implemented the methods. The result is polymorphism because each compression class has the same method signature but individual implementations of that signature.

The naming convention for interfaces is to use Pascal case, with an I prefix. The IFileCompression interface shown in Listing 7.1 is an example of such a name and interface definition.

Listing 7.1. Defining an Interface

 interface IFileCompression {   void Compress(string targetFileName, string[] fileList);   void Uncompress(       string compressedFileName, string expandDirectoryName); } 

IFileCompression defines the methods a class implements to work with other compression-related classes. The power of defining the interface concerns the ability to switch between implementations without modifying the calling code, as long as each compression class implements the IFileCompression interface.

One key characteristic of an interface is that it has no implementation and no data. Method declarations have a single semicolon in place of curly brackets after the header. Fields (data) cannot appear on an interface. When an interface requires the derived class to have certain data, it uses a property rather than a field. Since the property does not contain any implementation as part of the interface declaration, it doesn't reference a backing field.

Given that the purpose of the interface is to define the contract between multiple classes, defining private or protected members would make them inaccessible to other classes, defeating the purpose of the interface. Therefore, C# does not allow access modifiers on interface members, and instead it automatically defines them as public.

Essential C# 2.0
Essential C# 2.0
ISBN: 0321150775
EAN: 2147483647
Year: 2007
Pages: 185 © 2008-2017.
If you may any questions please contact us: