October 22, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

The Components of a Class

  • March 10, 2005
  • By Matt Weisfeld
  • Send Email »
  • More Articles »

The Nothingness of Null

In many programming languages, the value null represents a value of nothing. This might seem like an esoteric concept, but setting an attribute to nothing is a useful programming technique. Checking a variable for null can identify whether a value has been properly initialized. For example, you might want to declare an attribute that will later require user input. Thus, you can initialize the attribute to null before the user is actually given the opportunity to enter the data. By setting the attribute to null (which is a valid condition), you can check whether an attribute has been properly set.

As you know, it is always a good idea to initialize attributes in the constructors. In the same vein, it's a good programming practice to then test the value of an attribute to see whether it is null. This can save you a lot of headaches later if the attribute or object was not set properly. For example, if you use the myCab reference before a real object is assigned to it, you will most likely have a problem. If you set the myCab reference to null in the constructor, you can later check to see whether myCab is still null when you attempt to use it. An exception might be generated if you treat an uninitialized reference as if it were properly initialized.

The second constructor provides a way for the user of the class to initialize the Name and myCab attributes:

public Cabbie(String iName, String serialNumber) {
   name = iName;
   myCab = new Cab(serialNumber);
}

In this case, the user would provide two strings in the parameter list of the constructor to properly initialize attributes. Notice that the my Cab object is actually instantiated in this constructor:

myCab = new Cab(serialNumber);

At this point, the storage for a Cab object is allocated. Figure 3 illustrates how a new instance of a Cab object is referenced by the attribute myCab. Using two constructors in this example demonstrates a common use of method overloading. Notice that the constructors are all defined as public. This makes sense because, in this case, the constructors are obvious members of the class interface.

Figure 3: The Cabbie object referencing an actual cab object.

Accessors

In most, if not all, examples in this series, the attributes are defined as private so that a second object cannot access another object's attributes. It would be ridiculous to create an object in isolation—you want to share the appropriate information with other objects. Isn't it necessary to inspect and sometimes change another class's attribute? The answer is yes, of course. There are times when an object needs to access another object's attributes; however, it does not need to do it directly.

A class should be very protective about its attributes. For example, you do not want object A to have the capability to inspect or change the attributes of object B without object B having control. There are several reasons for this; the most important reasons really boil down to data integrity and efficient debugging.

Assume that there is a bug in the Cab class. You have tracked the problem to the Name attribute. Somehow, it is getting overwritten, and garbage is turning up in some name queries. If Name were public and any class could change it, you would have to go searching through all the possible code, trying to find places that reference and change Name. However, if you let only a Cabbie object change Name, you'd only have to look in the Cabbie class. This access is provided by a type of method called an accessor. Sometimes, accessors are referred to as getters and setters, and sometimes they're simply called get() and set(). By convention, in this series I'll name the methods with the set and get prefixes, as in the following:

// Set the Name of the Cabbie
public void setName(String iName) {
   name = iName;
}
// Get the Name of the Cabbie
public String getName() {
   return name;
}

In this snippet, a Supervisor object must ask the Cabbie object to return its name (see Figure 4.4). The important point here is that the Supervisor object can't simply retrieve the information on its own: it must ask the Cabbie object for the information. This concept is important at many levels. For example, you might have a setAge() method that checks to see whether the age entered was 0 or below. If the age is less than 0, the setAge() method can refuse to set this incorrect value. In general, the setters are used to ensure a level of data integrity.

Notice that the getCompanyName() method is declared as static, as a class method (as the name implies, class methods are owned by the class—not an individual object). Remember that the attribute companyName is also declared as static. A method, like an attribute, can be declared as static to indicate that there is only one copy of the method for the entire class.

Objects

Actually, there isn't a physical copy of each non-static method for each object. Each object would point to the same physical code. However, from a conceptual level, you can think of objects as being wholly independent and having their own attributes and methods.

Figure 4: Asking for information.

The following code fragment illustrates how to define a static method, and Figure 5 shows how more than one object points to the same code.

Static Attributes

If an attribute is static, and the class provides a setter for that attribute, any object that invokes the setter will change the single copy. Thus, the value for the attribute will change for all objects.

// Get the Name of the Cabbie
public static String getCompanyName() {
   return companyName;
}

Figure 5: Method memory allocation.

Public Interface Methods

Both the constructors and the accessor methods are declared as public, and are part of the public interface. They are singled out because of their specific importance to the construction of the class. However, much of the real work is provided in other methods. As mentioned in earlier articles, the public interface methods tend to be very abstract, and the implementation tends to be more concrete. For this class, you provide a method called giveDestination() that is the public interface for the user to describe where she wants to go:

public void giveDestination (){
}

What is inside of this method is not important at this time. The main point here is that this is a public method, and it is part of the public interface to the class.

Private Implementation Methods

Although all the methods discussed so far in this column are defined as public, not all the methods in a class are part of the public interface. Some methods in a class are meant to be hidden from other classes. These methods are declared as private:

private void turnRight(){
}
private void turnLeft() {
}

These private methods are simply meant to be part of the implementation, and not the public interface. You might ask who invokes these methods, if no other class can. The answer is simple—you might have already surmised that these methods are called internally from the class itself. For example, these methods could be called from within the method giveDestination:

public void giveDestination (){
   ... some code
   turnRight();
   turnLeft();
   ... some more code
}

The point here is that private methods are strictly part of the implementation, and are not accessible by other classes.

Conclusion

In this article, you have gotten inside a class and learned the fundamental concepts necessary to understand how a class is built. In future columns, you will continue to dissect more advanced components of class design.

References

Fowler, Martin. UML Distilled. Addison-Wesley Longman, 1997.

Gilbert, Stephen, and Bill McCarty. Object-Oriented Design in Java. The Waite Group, 1998.

Tyma, Paul, Gabriel Torok, and Troy Downing. Java Primer Plus. The Waite Group, 1996.

About the Author

Matt Weisfeld is an Assistant Professor at Cuyahoga Community College (Tri-C) in Cleveland, Ohio. Matt is a part of the Information Technology department, teaching programming languages such as C++, Java, and C# .NET as well as various Web technologies. Prior to joining Tri-C, Matt spent 20 years in the information technology industry gaining experience in software development, project management, business development, corporate training, and part-time teaching. Matt holds an MS in computer science and an MBA in project management.



Page 2 of 2



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel