Object-Oriented Concepts in .NET
- Classes—Wrapping Data and Behavior Together
- Inheritance—Defining Classes in Terms of One Another
- Polymorphism—Overriding One Class Method with Another
In This Chapter
ClassesWrapping Data and Behavior Together
InheritanceDefining Classes in Terms of One Another
PolymorphismOverriding One Class Method with Another
Starting with the release of Visual Basic 4.0, the capability to create classes has been intrinsic to the Visual Basic language. Some might say that Microsoft's move to support this was the true beginning of VB's evolution into an object-oriented language. Whenever it started, and whatever you thought of Visual Basic's prior ability (or inability) to support object-oriented (OO) concepts, .NET brings Visual Basic up to speed with all of the basic properties of an object-oriented programming language. The deep object support in Visual Basic .NET, and the .NET Framework in general, is certainly one of the most compelling changes offered in this new environment.
This chapter will focus on defining the concepts of object orientation as they relate to software development in general. In Chapter 4, "Introduction to the .NET Framework Class Library," we will also examine their specific manifestations in the .NET Framework.
There have been more than a few books written on object-oriented programming, so this chapter will not attempt to deliver a full treatise on a subject well deserving of hundreds of pages. Instead, we will cover only the ground that we need to cover so that programmers new to object-oriented programming and programmers with no OO experience at all will have a good backdrop of knowledge for exploring the .NET Framework Class Library.
We'll start by reviewing all of the pertinent characteristics of object-oriented languagesan obvious first step when you consider that the classes and other pieces of the Framework Class Library are all object-oriented in nature. Then we'll examine how these concepts have been brought to life inside of .NET and Visual Basic .NET, hopefully arming you with a solid-enough understanding of these concepts to make your programming experiences with the Framework Class Library more productive.
In years past, many developers have debated whether Visual Basic was an object-oriented language. Instead of investigating any of these prior claims, arguments, or discussions, let's focus instead on the here and now. Visual Basic .NET supports the major traits of an object-oriented language, including the capability to:
Wrap data and behavior together into packages called classes (this is a trait known as encapsulation)
Define classes in terms of other classes (a trait known as inheritance)
Override the behavior of a class with a substitute behavior (a trait known as polymorphism)
We'll examine each one of these traits in detail. We'll also examine ways in which you will see these concepts at work inside of the .NET Framework. Chapter 4 will continue this thread by specifically examining the nature of the Framework Class Library and attempting to relate these object-oriented concepts directly to the Framework Class Library.
ClassesWrapping Data and Behavior Together
Classes are blueprints or specifications for actual objects that we will create in our code. They define a standard set of attributes and behaviors. Because classes only define a structure or intent, they are virtual in nature. For instance, a class cannot hold data, it can't receive a message, and in fact can't do any processing at all. This is because classes are only meant to be object factories. Just like real engineering blueprints of a building, they only exist to construct something else. When we program, this "something else" we are trying to construct is an object. An object can hold data, can receive messages, and can actually carry out processing.
While you don't typically use the term class in your everyday (non-programming) life, we are all certainly familiar with the concept of objects. These are the things that surround us day in and day out; they are the nouns in our universe. We are used to interacting with objects. For example, you place a plate on your table for dinner. The plate has food on ita few different types of food, in fact. We can see that all of these things have distinct properties: The plate is white with a faint flower pattern, and the food has a particular texture, taste, and smell. We also expect that objects will allow us to interact with them in different ways.
Just like in the real world, code objects (we also call them instances) are actual physical manifestations of classes.
Classes as Approximations
If we discuss classes in the context of programming, we say that they establish a template for objects by defining a common set of possible procedures and data. Procedures are used to imbue the class with a set of behaviors; when implemented in a class they are called methods. Classes maintain data inside of properties (which may or may not be visible to other classes). Behaviors are the verbs of classes, and properties are the nouns. A car, for instance, will accelerate in a prescribed fashion. This would be a behavior. A car will also have a specific weight, color, length, and so on. These are properties. From a technical, implementation point of view, there is actually no difference between the way that methods and properties are implemented. They both have function signatures, and both execute some body of code. In addition, both of them can accept parameters and return values.
There are some general guidelines for when to use properties versus methods (and vice versa), but probably the best advice is to just be consistent. Most of the time, these rules will help steer you to the correct decision:
Use a method if you are going to be passing in more than a few parameters.
If you find yourself writing a method called GetXXX or SetYYY, chances are good this should be a property instead.
Methods are more appropriate than properties if there will be many object instantiations or inter-object communication inside of the function.
Properties, when implemented, should be stateless with respect to one another. In other words, a property should not require that another property be set before or after it is set. If you find this kind of dependency inside of a property, it should probably be a method instead.
Classes are typically constructed to mimic, or approximate, real-world physical structures or concepts. By using classes in your code, you can simplify both your architecture and your understanding of the code; this is due to the inherent approachability of objectsyour mind is used to deal with objects. For example, which do you suppose would make more intuitive sense to you?
You are writing code to move an icon from the left side of the screen to the right side of the screen. The procedural programming way would probably have you calling some API function (maybe it's called SystemDskRsrcBlit) and passing parameters into the function call. But, what if you were free to do this:
Create an icon object
Tell it to MoveLeft
The object-oriented way just seems to make more sense to usit seems to appeal to the way that our minds are wired.
The difference between the system that we are programming and the real-world process that we are modeling is often referred to as the semantic gap. You could summarize some of what we have been talking about here by saying that object- oriented programming aims to reduce the semantic gap between programming and the real world.
Of course, just because the basic premises of objected-oriented programming are simple to understand doesn't mean that the actual programming of object-oriented systems is trivial. Once you can work your way through the syntax and condition yourself to think in an object-like fashion while actually designing your applications, some of the perceived complexity associated with software development will begin to fade.
Talking Between Classes
We have said that classes define a set of behaviors. These behaviors would be useless to us unless we had a way to actually stimulate or initiate a particular behavior. Therefore, we have the concept of messaging. A message is nothing more than a request, from one object to another, to perform some sort of action. The receiving object may choose to ignore the action (especially if it doesn't have a behavior defined that would map to the requested action) or it may perform a specific action that could, in turn, send messages to other objects.
A core tenet of object-oriented systems is that classes think for themselves. A particular class knows how it should react to an incoming message; the calling class isn't forced to understand how or why the receiving class behaves the way that it does. This is the essence of information hiding. In information hiding, an object hides its internal machinations from other objects (see Figure 3.1). Information hiding is important because it helps reduce the overall design complexity of an application. In other words, if Class A doesn't have to implement code to understand how Class B operates, we have just reduced the complexity of the code.
As programmers, we initiate a message from one class to another by calling a method or property on the target class. Part of this message that we send encapsulates any parameters or data needed by the receiving class to execute the action.
Thus, we have classes in an object-oriented programming environment. A physical manifestation of a class in the programming world consists of code that defines these attributes and behaviors through property and method routines.
In this book, our focus on the Framework Class Library will introduce you to new classes in each chapter. They will exhibit all of the traits and characteristics of the classes that we have just defined.
Now, let's move on and discuss the next OO trait of Visual Basic .NETinheritance.
Figure 3.1 Messaging and information