Solution to Question 13-1. The interface defines the methods, properties, and so forth that the implementing class must provide. The implementing class provides these members and, optionally, additional members.
Solution to Question 13-2. Every class has exactly one base class (either explicit, or the object
class by default), but may implement zero, one, or more interfaces. An abstract base class serves as the base to a derived class that must implement all of its abstract methods; otherwise, that derived class is also abstract.
Solution to Question 13-3. You can’t create an instance of an interface. To access the interface methods, you must create an instance of a class that implements the interface.
Solution to Question 13-4. You’d use the following syntax to create a class that inherits from a parent and implements two interfaces:
class MyClass : MyBase, ISuppose, IDo {...}
Note that the base class must come first after the colon.
Solution to Question 13-5. The is
and as
operators are used to test whether a class implements an interface.
Solution to Question 13-6. is
returns a Boolean, which is false if the interface is not implemented. as
attempts to make the cast, unlike is
, and returns null if the cast fails. Using the as
operator can be more efficient.
Solution to Question 13-7. Extending an interface is very much like deriving a class. The new interface inherits all the members of the parent interface, and can also include additional methods.
Solution to Question 13-8. The syntax for extending an interface is:
ExtendedInterface :
OriginalInterface
For example, you would read:
ILoggedCompressible : ICompressible
as "ILoggedCompressible
extends ICompressible
.”
Solution to Question 13-9. The class implementing a method of the interface can mark that method virtual
, and the implementation of the method can then be overridden in derived classes.
Solution to Question 13-10. Explicit interface implementation identifies the member of the interface by naming the interface itself (e.g., IStorable.Write( )
). This is done to differentiate implementation methods when there might otherwise be an ambiguity, such as when implementing multiple interfaces that have methods with the same signature.
Solution to Exercise 13-1. Define an interface IConvertible
that indicates that the class can convert a string to C# or VB. The interface should have two methods: ConvertToCSharp
and ConvertToVB
. Each method should take a string and return a string.
In this exercise, you’re not actually creating code that will run; you’re just defining the interface. As you learned, the methods of the interface don’t have any implementation, they just have signatures. Example A-34 shows this simple interface.
Example A-34. One solution to Exercise 13-1
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Exercise_13_1 { interface IConvertible { string ConvertToCSharp(string stringToConvert); string ConvertToVB(string stringToConvert); } }
Solution to Exercise 13-2. Implement that interface and test it by creating a class ProgramHelper
that implements IConvertible
. You don’t have to write methods to convert the string; just use simple string messages to simulate the conversion. Test your new class with a string of fake code to make sure it works.
In this exercise, you’ll actually implement the interface that you derived earlier, although your code doesn’t need to do anything more than say that it’s converting the string. The string we used in Run( )
is just dummy text representing a string of VB code. In Run( )
, we pass the string to the ConvertToVB( )
method, and then pass it back to the ConvertToCSharp( )
method. Example A-35 shows the way we did it.
Example A-35. Our solution to Exercise 13-2
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Exercise_13_2 { interface IConvertible { string ConvertToCSharp(string stringToConvert); string ConvertToVB(string stringToConvert); } public class ProgramHelper : IConvertible { public ProgramHelper( ) // constructor { Console.WriteLine("Creating ProgramHelper"); } public string ConvertToCSharp(string stringToConvert) { Console.WriteLine("Converting the string you passed in to CSharp syntax"); return "This is a C# String."; } public string ConvertToVB(string stringToConvert) { Console.WriteLine("Converting the string you passed in to VB syntax"); return "This is a VB String."; } } class Tester { public void Run( ) { // Create a ProgramHelper object ProgramHelper theProgramHelper = new ProgramHelper( ); // convert a line of CSharp to vb string vbString = theProgramHelper.ConvertToVB("This is a VB String to convert."); Console.WriteLine(vbString); // convert the converted line back to CSharp string cSharpString = theProgramHelper.ConvertToCSharp(vbString); Console.WriteLine(cSharpString); } static void Main( ) { Tester t = new Tester( ); t.Run( ); } } }
Solution to Exercise 13-3. Extend the IConvertible
interface by creating a new interface, ICodeChecker
. The new interface should implement one new method, CodeCheckSyntax
, which takes two strings: the string to check and the language to use. The method should return a bool
. Revise the ProgramHelper
class from Question 13-2. to use the new interface.
The first thing you need to do in this exercise is to add the ICodeChecker
interface with its bool
, making sure to use the proper syntax to extend IConvertible
. Change ProgramHelper
to implement ICodeChecker
, which also means that it implements IConvertible
. We’ve added some code in Run( )
to convert the string, then check the syntax, convert it back again, and check the syntax again. Example A-36 shows how we did it.
Example A-36. One solution to Exercise 13-3
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Exercise_13_3 { interface IConvertible { string ConvertToCSharp(string stringToConvert); string ConvertToVB(string stringToConvert); } interface ICodeChecker : IConvertible { bool CheckCodeSyntax(string stringToCheck, string whichLang); } public class ProgramHelper : ICodeChecker { public ProgramHelper( ) // constructor { Console.WriteLine("Creating ProgramHelper"); } public string ConvertToCSharp(string stringToConvert) { Console.WriteLine("Converting the string you passed in to CSharp syntax"); return "This is a C# String."; } public string ConvertToVB(string stringToConvert) { Console.WriteLine("Converting the string you passed in to VB syntax"); return "This is a VB String."; } public bool CheckCodeSyntax(string stringToCheck, string whichLang) { switch (whichLang) { case "CSharp": Console.WriteLine("Checking the string for C# Syntax: {0}", stringToCheck); return true; case "VB": Console.WriteLine("Checking the string for VB Syntax: {0}", stringToCheck); return true; default: return false; } } } // end class ProgramHelper class Tester { public void Run( ) { // Create a ProgramHelper object ProgramHelper theProgramHelper = new ProgramHelper( ); // convert a line of CSharp to VB string cSharpString = theProgramHelper.ConvertToCSharp( "This is a VB string to convert."); Console.WriteLine(cSharpString); Console.WriteLine("Checking the string for syntax... Result {0}", theProgramHelper.CheckCodeSyntax( cSharpString, "CSharp")); // convert the converted line back to VB string vbString = theProgramHelper.ConvertToVB(cSharpString); Console.WriteLine(vbString); Console.WriteLine("Checking the string for syntax... Result {0}", theProgramHelper.CheckCodeSyntax( vbString, "VB")); } static void Main( ) { Tester t = new Tester( ); t.Run( ); } } }
Solution to Exercise 13-4. Demonstrate the use of is
and as
. Create a new class, ProgramConverter
, which implements IConvertible
. ProgramConverter
should implement the ConvertToCSharp( )
and ConvertToVB( )
methods. Revise ProgramHelper
so that it derives from ProgramConverter
and implements ICodeChecker
. Test your class by creating an array of ProgramConverter
objects, some of which are ProgramConverter
s and some of which are ProgramHelper
s. Then call the conversion methods and the code check methods on each item in the array to test which ones implement ICodeChecker
and which ones do not.
For this exercise, you need to first define the new class ProgramConverter
, and give it the ConvertToCSharp( )
and ConvertToVB( )
methods. Then derive ProgramHelper
from ProgramConverter
, You can remove the ConvertToCSharp( )
and ConvertToVB( )
methods from ProgramHelper
, because they’ll be inherited from ProgramConverter
. In Run( )
, you’ll need to create the array of ProgramConverter
objects, either manually, or randomly as we did in the chapter. Then use the is
or as
operator to test each element of the array to see which interfaces they implement. Example A-37 shows how we did it.
Example A-37. Our solution to Exercise 13-4
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Exercise_13_4 { interface IConvertible { string ConvertToCSharp( string stringToConvert ); string ConvertToVB( string stringToConvert ); } interface ICodeChecker : IConvertible { bool CheckCodeSyntax( string stringToCheck, string whichLang ); } public class ProgramConverter : IConvertible { public ProgramConverter( ) // constructor { Console.WriteLine( "Creating ProgramConverter" ); } public string ConvertToCSharp( string stringToConvert ) { Console.WriteLine( "Converting the string you passed in to CSharp syntax" ); return "This is a C# string."; } public string ConvertToVB( string stringToConvert ) { Console.WriteLine( "Converting the string you passed in to VB syntax" ); return "This is a VB string."; } } public class ProgramHelper : ProgramConverter, ICodeChecker { public ProgramHelper( ) // constructor { Console.WriteLine( "Creating ProgramHelper" ); } public bool CheckCodeSyntax( string stringToCheck, string whichLang ) { switch ( whichLang ) { case "CSharp": Console.WriteLine("Checking the string {0} for C# Syntax", stringToCheck ); return true; case "VB": Console.WriteLine("Checking the string {0} for VB Syntax", stringToCheck ); return true; default: return false; } } } class Tester { static void Main( ) { Tester t = new Tester( ); t.Run( ); } public void Run( ) { ProgramConverter[] converters = new ProgramConverter[4]; converters[0] = new ProgramConverter( ); converters[1] = new ProgramHelper( ); converters[2] = new ProgramHelper( ); converters[3] = new ProgramConverter( ); foreach ( ProgramConverter pc in converters ) { string vbString = pc.ConvertToCSharp( "This is a VB string to convert."); Console.WriteLine( vbString ); ProgramHelper ph = pc as ProgramHelper; if ( ph != null ) { ph.CheckCodeSyntax( vbString, "VB" ); } else { Console.WriteLine( "No vb syntax check - not a Program helper" ); } string cSharpString = pc.ConvertToCSharp( vbString ); Console.WriteLine( cSharpString ); if ( ph != null ) { ph.CheckCodeSyntax( vbString, "CSharp" ); } else { Console.WriteLine( "No csharp syntax check - not a Program helper" ); } } } } }