Creating a Constructor

Imagine that you want to write a program using several critters. Each critter could have a different name and different characteristics (perhaps different starting values for hunger and happiness). Using the Critter class from Chapter 4, you could do it, but you’d have to create each critter in several steps. First, you’d have to create the critter, and then you’d need another statement of code to modify each characteristic. It would look something like this:

Critter myCritter = new Critter();
myCritter.name = "alpha";
myCritter.age = 10; 

Although this is not difficult, a more convenient way to create a critter would enable you to initialize all its values at the same time. You could set up a critter with a line like this:

Critter myCritter = new Critter("alpha", 10, 9, 0);

The critter automatically assumes the name alpha, a happiness level of 10, a hunger level of 9, and an age of 0. (The age of 0 means that it will age after the first turn) You can apply a set of parameters whenever you create an instance of the critter class. Classes (such as the Critter) can have a special method called a constructor. A class’s constructor is a special method that is used to help create the critter. The constructor is automatically called whenever you create an instance of the class when using the new keyword.

Adding a Constructor to the Critter Class

I took the Critter class from Chapter 4 and added a constructor to it:

using System;

namespace CritterConstructor
{
   /// <summary>
   /// Critter with a constructor
   /// </summary>

     public class Critter {
       // your basic critter
       //instance variables
       private string pName;
       private int pFull = 10;
       private int pHappy = 10;
       private int pAge = 0;

       //constructor
       public Critter(string theName, int fullness, int happiness, int theAge){
         name = theName;
         pFull = fullness; 
          pHappy = happiness;
          pAge = theAge;
       } // end constructor

       public string name
       public string talk() …
       public void age() …
       public void play() …
       public void eat() …
    } // end class
} // end namespace

I minimized all the properties and methods so that you can focus on the new part of the critter. Constructors are special methods that have the same name as the class. A constructor is always public, and you do not have to specify a return value because the constructor will return an instance of the class as its value. Whenever you make an instance of a class (remember, the class is a recipe, and instances are the cookies), the computer looks for a constructor. The constructor usually has special instructions for getting the class started. In this case, I added a constructor for the Critter class that accepts four parameters. Each parameter is mapped to a specific instance variable. Constructors are typically used to initialize instance variables, even in more complex classes. The other nice thing about a constructor is that you know that any code inside a constructor will happen as soon as the object is created. Therefore, any code you want to run at the beginning of the class’s life span should be written in the constructor. Constructors can have parameters just like any other method.

The Critter class does not have a Main() method. In any given namespace, it generally makes sense for only one class to have a Main() method. However, your project can (and usually will) have many classes and several instances of each class. The Critter class is not intended to be an executable program, so I will use it inside other classes that do have a Main() method. When you look at the files created by the .NET compiler, the programs that have a Main() method usually have an associated .exe (executable) file. Those that do not have a Main() method are compiled into dynamic linked libraries (.dll files). You might have heard that the only difference between an .exe file and a .dll file is that an executable (.exe) file has a Main() method and a dynamically linked library (dll) doesn’t. This is a generalization (and not completely true). Important internal differences exist between these files, but for the purposes of this book, this is a reasonable simplification.

Creating the CritViewer Class

If you type in the Critter class from the preceding section and attempt to run it, it will compile, but it won’t run. Often, you make classes that are meant to be used as parts inside other classes. A gas tank, for example, is an important part, or class, of the automobile. Gas tanks have parts and require assembly. When a gas tank is finished, it is sent to the auto assembly plant and installed. The gas tank is a class, but you can’t drive it because it’s designed to be part of a larger assembly. The program itself is one object (like the car), but it usually comprises constituent objects. Only the primary object needs a Main() method.

The Critter class will not stand on its own, so you need a container class to demonstrate the critter’s capabilities. In Chapter 4, you use a menu class to do this. Here, you use a much simpler program to contain the critter so that you can concentrate on new ways of building objects. The Critter Constructor program featured in Figure 5.4 demonstrates a version of the Critter program, with one class for a viewer and the modified Critter class with a constructor.

Figure 5.4. The critter viewer demonstrates the basic functionality of the critter.


Building a simple container to demonstrate and test a new class is a common strategy of object-oriented programmers. Because an object is encapsulated, it should work as well in one program as in another. You can create very straightforward programs to test your objects before you use the objects in a more complex program. With this technique, you are more likely to isolate errors in your custom classes before you add them to complex assemblies, where more can go wrong.

To demonstrate my new critter, I’ll build a CritterViewer class, which is reasonably simple:

using System;

namespace CritterConstructor
{
  /// <summary>
  /// CritViewer is a simple class designed simply to hold a critter
  /// Demonstrates self-instantiation
  /// Andy Harris, 12/21/01
  /// </summary>
  class CritViewer
  {
    static void Main(string[] args)
    {
      // the main method simply creates an instance of the
      /// critviewer object
      CritViewer cv = new CritViewer();
    } // end main

    //This next method is the constructor for CritViewer
    public CritViewer(){
      Critter myCritter = new Critter("alpha", 10, 10, 0);
      Console.WriteLine("I'm in critViewer");
      Console.WriteLine(myCritter.talk());

      Console.WriteLine();
      Console.WriteLine("Please press Enter key to continue");
      Console.ReadLine();
    } // end constructor
  } // end CritViewer Class
}  // end namespace

Note the simplicity of the Main() method in this code:

static void Main(string[] args)
     {
       // the main method simply creates an instance of the
       /// critviewer object
       CritViewer cv = new CritViewer();
     } // end main

Reviewing the Static Keyword

So far in this book, most of the code appears in the Main() method of the program. Although this approach is fine for these simple programs, it has limitations because the Main() method must be declared a static method. The keyword static in the preceding code means that the Main() method can be called before the class exists. A static method can be called without requiring an instance of the class. For example, most of the methods in the Convert class in Chapter 2, “Branching and Operators: The Math Game,” are static methods. You don’t have to create an instance of the Convert class to use its methods. Likewise, the WriteLine() method of the Console class is static. Static methods can be useful, but they have a serious limitation: Static methods cannot refer to instance variables because the instance variables have meaning only in an instance. The Main() method must be declared static, because it is the first entry into the program from the operating system. To avoid some of these limitations of static methods, the Main() method is usually much simpler than it has been in the examples you have seen so far in this book.

That sounds complicated, but it isn’t. The keyword static can also be read as class-level. The keyword instance in the preceding code refers to instance-level. Recall the cookie recipe analogy. A recipe is a class, and the cookies are instances of that class. A static method belongs to the entire class, not to a specific instance. In other words, a static method is a method that can be applied to the class, but not necessarily to the instances of that class. A recipe class may have copy and e-mail methods. An instance of a cookie is not required to invoke the class-level methods. It doesn’t make sense for e-mailing to belong to cookies (the instances of the class). (Besides, cookie dough is very hard on floppy drives.) E-mailing is a method of the recipe (the class itself), so Cookie.email() would most likely be a static method. The e-mail method is not concerned with actual cookie instances, so it makes sense that the static method would not have access to the details of individual cookies. Because you are e-mailing the recipe, not a cookie, the e-mail method shouldn’t have access to the bitesMissing property of a cookie because bitesMissing is an instance-level property (as most properties are).

Calling a Constructor from the Main() Method

The Main() method has to be a static method because it is called from the operating system. When you run a C# program, the first thing the operating system does is look for a Main() method. That Main() method runs before any specific classes are instantiated. Usually, it calls a constructor or two to get things started. A Main() method rarely contains much more than one call to a constructor because the static limitations can get in the way. Instead, the Main() method usually creates an instance of a class or two. You might be surprised to see which class the CritViewer’s Main() method creates:

CritViewer cv = new CritViewer();

The Main() method of the CritViewer class creates an instance of the CritViewer class! This idea might seem like the work of the department of redundancy department, but it makes sense in terms of static methods. Main() is a static method, which means that it runs before an instance of the CritViewer object occurs. Because I really want an instance of the object here, I use the Main() method to create an instance of the class. Objects with a Main() method often utilize this technique to pull themselves into existence. When you run a program that contains an object with a Main() method, that Main() method runs before any other code executes. The main method calls the class’ s constructor, which finishes creating the class.

If more than one class has a Main() method, you can set the properties of the project in the project window to determine which object’s Main() method will start the program.

Examining CritViewer’s Constructor

The rest of the work in the CritViewer class occurs in its constructor:

//This next method is the constructor for CritViewer
    public CritViewer(){
      Critter myCritter = new Critter("alpha", 10, 10, 0);
      Console.WriteLine("I'm in critViewer");
      Console.WriteLine(myCritter.talk());

      Console.WriteLine();
      Console.WriteLine("Please press Enter key to continue");
      Console.ReadLine();
    } // end constructor

Constructors are instance-level because they create an instance of an object. The constructor of the critter viewer creates an instance of the Critter class. I took advantage of the critter’s newfound constructor capabilities. Building the critter with this four-parameter constructor is convenient because it saves you a lot of typing time.

Working with Multiple Files

Until now, all the source code in your programs has existed in a single file on the disk. This is fine for small programs but becomes unwieldy when your programs are longer. After you start building programs with multiple classes, you should open a new file for every class. The default file that loads in the editor when you start a program already has a Main() method. You usually use that program as the container class to hold your other classes. Figure 5.5 demonstrates how to create a new class in the Visual Studio editor.

Figure 5.5. To create a new class, choose Add Class from the Project menu, then click Class.


The Visual Studio IDE enables you to have many files open at the same time. This can be very handy when your programs become complex. As a default, the new class will belong to the same namespace as your existing classes because all the classes in your project are meant to work together.

The IDE also has a class viewer feature for looking at all the parts of your object. The Class View, illustrated in Figure 5.6, is usually available in the right segment of the editor.

Figure 5.6. The Class View is used to navigate the entire project.


This Class View is a specialized object browser containing the objects in your project. (You can also view your project in the object browser window if you like, but the Class View is usually more convenient for this purpose.) You can expand the various elements of your project to see every property and method of your custom objects. When you double-click a property or method in this menu, you are taken directly to the code related to that member. You can use the Class View as a menu system for your code, giving you an easy way to jump to whatever part of the code you want to view.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.17.18