Implementing .NET Framework Interfaces

   

For this exercise, you're going to add on to last hour's project and create your own collection class. In case you don't have the project anymore, you can create a new project. Click New, Project from the File menu within the IDE. Select Visual C++ Project from the list of project types and select Managed C++ Application from the list of templates. Give your project the name CollectionTest and click OK to create the project.

The collection you will create is simply a specialized derivation of the stack collection that only accepts strings rather than any System::Object-based objects. To begin, create a new managed C++ class. The easiest way to do this is to select Project, Add Class from the main menu. Select the Generic C++ Class list item and click Open. Give your class the name StringStack and click Finish to create the class. Because we are working within the .NET Framework, you'll have to convert the generic class that was created into a managed C++ class.

Open the StringStack.h file and import the mscorlib.dll file with the #using statement. Next, declare the namespaces you will be using with the using keyword. The namespaces that this class needs are System and System::Collections. Finally, add the __gc keyword in front of the class keyword within your class. Your code should now appear similar to Listing 17.1.

Listing 17.1 Creating the StringStack Managed Class
 1: #using <mscorlib.dll>  2: #include <tchar.h>  3: #include <windows.h>  4:  5: using namespace System;  6: using namespace System::Collections;  7:  8: public __gc class StringStack  9: { 10:     public: 11:       StringStack(void); 12:       ~StringStack(void); 13: }; 

Implementing an interface is very similar to deriving a class from a base class. In other words, to implement an interface, you use inheritance. In order to create a collection class that supports enumeration, you must implement at least two collection interfaces: ICollection and IEnumerable. This is done by creating a comma-delimited list following the class name declaration, separated by a colon. The following code snippet shows the StringStack class implementing the two collection interfaces:

 public __gc class StringStack : public ICollection, public IEnumerable 

Before you begin the implementation of the StringStack class, create an instance of the object in the CollectionTest.cpp file. The first step is to include the StringStack header file. Next, create a function named TestStringStack above the _tmain function. The TestStringStack should take no parameters and have a return type of void. Within the TestStringStack function, declare a StringStack pointer and assign to it a new instance of a StringStack object. Finally, call the TestStringStack function from the _tmain function. Your CollectionTest.cpp file should appear similar to Listing 17.2.

Listing 17.2 Creating the StringStack Object
 1: #include "stdafx.h"  2:  3: #using <mscorlib.dll>  4: #include <tchar.h>  5: #include <windows.h>  6:  7: #include "StringStack.h"  8:  9: using namespace System; 10: 11: void TestStringStack() 12: { 13:      // create stack 14:     StringStack* pStringStack = new StringStack(); 15: } 16: 17: // This is the entry point for this application 18: int _tmain(void) 19: { 20:     TestStringStack(); 21: 22:     return 0; 23: } 

Now would be a good time to compile your application. If you've followed the directions so far, any errors you see are supposed to be there. You learned earlier that an interface is like a contract. When a class specifies that it implements an interface but fails to add the methods and properties of that interface, it has broken that contract, causing the compiler to complain.

Within the Visual Studio .NET IDE are two ways to view build errors. The first way is through the Task List window. This window, shown in Figure 17.1, displays the official error message and doesn't contain any extra information the compiler may give you. To view any extra information, open the Output window to view the data the compiler has emitted. If you don't see either of these two windows, you can click Views, Other Windows and then select either Task List or Output to view the respective window.

Figure 17.1. The Task List window showing an interface error.

graphics/17fig01.jpg

The error within the Task List window is error C2259, which mentions that you cannot instantiate the StringStack abstract class. Looking at the Output window tells you the reason. After the text of the error, the compiler tells you that several pure virtual functions were not defined. The pure virtual functions are the interface functions you must implement within your class.

Implementing the StringStack Collection

Because your class implements two separate interfaces, you have to implement the pure virtual functions each interface contains. Of course, you have no idea what they are, which is why you have to refer to documentation. If you look up ICollection and IEnumerable within the .NET Framework documentation, you'll find the methods and properties you need to implement listed.

graphics/bulb.gif

Sometimes you might have to use an interface that, for some reason, does not have any documentation, or the documentation isn't available at the time. As mentioned, the compiler gives you rich information on what pure virtual functions you failed to implement. The compiler even goes as far as to tell you the exact signature of the interfaces. You can use the information from the compiler to ensure that you implement the correct interface methods.

An interface can contain zero or more methods and zero or more properties. A property is similar to a member variable within a class or structure. A client using that interface and a property within that interface can set the property to a certain value and also get the value of that property. In the documentation for the ICollection interface, the properties are listed first, followed by the methods. One of the properties listed is the IsSynchronized property. Properties, although similar to member variables, are not set or retrieved like member variables; rather functions are used to do so. Therefore, when you implement a property for an interface within Visual C++ .NET, you need to preface the property with either get_ or set_. The IsSynchronized property, therefore, can translate into two functions within your class: get_IsSynchronized and set_Is Synchronized. However, the documentation states that this is a read-only property, which means there is no set_IsSynchronized function.

Using the documentation or the compiler output as a guide, add the necessary function declarations for the ICollection interface and the IEnumerable interface. Your StringStack.h file should appear similar to Listing 17.3.

Listing 17.3 Declaring the ICollection and IEnumerable Interface Methods
 1: #pragma once  2:  3: #using <mscorlib.dll>  4: #include <tchar.h>  5: #include <windows.h>  6:  7: using namespace System;  8: using namespace System::Collections;  9: 10: public __gc class StringStack 11:     : public ICollection 12:     , public IEnumerable 13: { 14:     public: 15:         StringStack(void); 16:         ~StringStack(void); 17: 18:         // ICollection properties 19:         int get_Count(); 20:         Object* get_SyncRoot(); 21:         bool get_IsSynchronized(); 22: 23:          // ICollection methods 24:          void CopyTo( Array* pDest, int iIndex ); 25: 26:          // IEnumerable method 27:         IEnumerator* GetEnumerator(); 28: }; 

The final step is to now implement the functions for the StringStack class. Because you are creating a stack class, you will use the standard stack functions Push and Pop.

However, the Stack class within the .NET Framework accepts any object derived from System::Object, but your class is specialized and only accepts String objects. Therefore, your Push function takes a single String parameter, whereas your Pop function returns a String object. Also, because you are creating a stack, you can create a private Stack variable and pass most of the function calls to that private variable, thus freeing yourself from having to implement a stack data structure. All you need to pay close attention to is that the necessary casting is performed as you convert from String to Object, and vice versa.

Because we want to concentrate on interfaces this hour, we will forgo the discussion on how to implement the functions themselves. The code for the StringStack implementation can be found on the Sams Web site.


   
Top


Sams Teach Yourself Visual C++. NET in 24 Hours
Sams Teach Yourself Visual C++.NET in 24 Hours
ISBN: 0672323230
EAN: 2147483647
Year: 2002
Pages: 237

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