Free mag vol1 | Page 346

CHAPTER 8  WORKING WITH INTERFACES When you run this application, the class name of each class prints out to the console, via the GetType() method you inherit from System.Object. As explained in Chapter 15, this method (and .NET reflection services) allow you to understand the composition of any type at runtime. In any case, the output of the previous program is shown next: ***** A First Look at Interfaces ***** Your clone is a: String Your clone is a: OperatingSystem Your clone is a: SqlConnection Another limitation of abstract base classes is that each derived type must contend with the set of abstract members and provide an implementation. To see this problem, recall the shapes hierarchy we defined in Chapter 6. Assume we defined a new abstract method in the Shape base class named GetNumberOfPoints(), which allows derived types to return the number of points required to render the shape: abstract class Shape { ... // Every derived class must now support this method! public abstract byte GetNumberOfPoints(); } Clearly, the only class that has any points in the first place is Hexagon. However, with this update, every derived class (Circle, Hexagon, and ThreeDCircle) must now provide a concrete implementation of this function, even if it makes no sense to do so. Again, the interface type provides a solution. If you define an interface that represents the behavior of “having points,” you can simply plug it into the Hexagon type, leaving Circle and ThreeDCircle untouched.  Source Code The ICloneableExample project is located under the Chapter 8 subdirectory. Defining Custom Interfaces Now that you better understand the overall role of interface types, let’s see an example of defining and implementing custom interfaces. To begin, create a brand-new Console Application named CustomInterface. Using the Project  Add Existing Item menu option, insert the file(s) containing your shape type definitions (Shape.cs and DerivedShapes.cs in the book’s solution code) created back in Chapter 6 during the Shapes example. After you have done so, rename the namespace that defines your shape-centric types to CustomInterface (simply to avoid having to import namespace definitions in your new project): namespace CustomInterface { // Your shape types defined here... } 284