- The Takeaway
- The Base Class
- C# enum Types
- Inheriting from the Base Class
- Putting It All Together
- C++ Versus C#
- Conclusion
Putting It All Together
It’s time now to put all the code together and see what it looks like when the program is run. Listing 8 illustrates the main program.
Listing 8 The Main Program
static void Main(string[] args) { InvoiceDocument anInvoiceDoc = new InvoiceDocument( 133, "A Big Customer", (int)documentType.INVOICE, 3500); Console.WriteLine( "Invoice name: {0}. Price value: {1}.", anInvoiceDoc.DocumentName, anInvoiceDoc.getPriceValue()); anInvoiceDoc.StoreDocument(); // Various workflows // Sending documents to recipients // Signing documents, archiving, etc. // Then finally... Console.ReadLine(); }
Executing the code in Listing 8 produces the output illustrated in Figure 1.
Figure 1 Running the program.
In the first line of Figure 1, you can see that the base class 4-parameter constructor is called. This is correct because the instantiation of the object anInvoiceDoc in Listing 8 has four parameters. Listing 5 illustrates the source code for the base class constructor as discussed above. Once the object anInvoiceDoc is created in Figure 1, I display some of the member data—specifically the customer name ("A Big Customer") and the price (3500).
Notice in Listing 8 that I do have to cast the enum type as an int in the InvoiceDocument constructor invocation. This is a type safety C# requirement—the code won't compile without this cast.
The last thing of interest to note in Listing 8 is an invocation of the method StoreDocument(). This is an abstract base class method, which means it has no content in the base class. It's just a placeholder that exists so that subclasses can implement it as they wish. The reasons why you use such object-oriented constructs are varied. One rationale is our old friend: the separation of concerns. The base class may simply not have a clue as to how the abstract method will be used in subclasses. Or subclasses may have such specialized needs that they must override the method. The classic illustration of this principle is in graphics programs where you define a base class to represent all shapes. In the base class, you also provide an abstract draw() method. Then, as your inheritance tree grows, each shape subclass implements its own draw() code. This is polymorphism in action, where the code can take on a number of different shapes as dictated by the abstract members.
In the current example of document management, why do I use an abstract base class method called StoreDocument()? Well, each derived document type might have specific storage requirements. There might even be regulatory requirements for storage needs depending on the type of document. The key point is that the use of an abstract base class member provides flexibility. One document type might be written to a file server, while another is written to a revision control system, and so on.