Tuesday, August 11, 2009

BASICS OF OBJECT-ORIENTED PROGRAMMING

This chapter is aimed at an audience unfamiliar with the basic concepts of object-oriented programming (OOP).
The intent is to provide a general overview of OOP with a view toward using PHP effectively. We’ll restrict the discussion to a few basic concepts of OOP as it relates to PHP, though it is sometimes useful to look at other object-oriented (OO) languages such as Java or C++.
We’ll discuss three aspects of object orientation in this chapter: class, access modifiers, and inheritance. Although OOP may be a different programming paradigm, in many respects it’s an extension of procedural programming, so where appropriate, I’ll use examples from procedural programming to help explain these concepts. Later chapters will return to the topics introduced here and refine them through the use of concrete examples.

Class

You can’t have OOP without objects, and that’s what classes provide. At the simplest level, a class is a data type. However, unlike primitive data types such as an integer, a float, or a character, a class is a complex, user-defined data type. A class is similar to a database record in that it encapsulates the char- acteristics of an object. For example, the record of a Person might contain a birth date, an address, a name, and a phone number. A class is a data type made up of other data types that together describe an object.

Classes Versus Records

Although a class is like a record, an important difference is that classes con- tain functions as well as different data types. And, when a function becomes part of a data type, procedural programming is turned on its head, quite literally, as you can see in the following example syntax. A function call that looked like this:

function_call($somevariable);

looks something like this with OOP:

$somevariable->function_call();

The significant difference here is that OO variables don’t have things done to them; they do things. They are the actors rather than the acted upon, and for this reason they are said to behave. The behavior of a class is the sum of its functions.

A Cohesive Whole

Procedural programmers often work with code libraries. These libraries usually group related functions together. For instance, all database functions might be grouped together in a file called dbfunctions.inc. The functions that make up an object’s behavior should also be related to one another, but in a much stronger fashion than functions in the same library. Just as the different ele- ments of a Person record describe an individual, so too should the behavior of a class describe the class. In order for something to be an object, it should be a cohesive whole incorporating appropriate characteristics and appropriate behavior.

Objects Are Instances

Classes aren’t themselves objects, but a way of creating objects—they are templates or blueprints that form the model for an object. When speaking loosely, these two terms are sometimes used interchangeably, but strictly speaking an object is an instance of a class. This is somewhat like the difference

between the concept of an integer and a specific variable $x with a specific value. The concept of a class as a template for an object becomes clearer in the context of inheritance, especially when we discuss multiple inheritance (a topic we’ll deal with shortly).

Objects Need Access Modifiers

OOP is made possible by using this simple concept of a class as a cohesive aggregate of characteristics and behaviors—as you’ll see in Chapter 3, this is exactly what objects are in PHP 4—but one of the most important features of any OO language is the use of access modifiers. Access modifiers refine the object model by controlling how an object is used or reused. Simply put, access modi- fiers provide guidance about what you can and cannot do with an object.
To get a sense of what this means, let’s use an example from procedural programming.
Let’s define a subroutine as a function that is never invoked directly but that is only called by other functions. Now suppose you’re a procedural pro- grammer with a library of functions and subroutines that is used by several other programmers. The ability to flag subroutines as secondary would be helpful in instructing others how to use your library, but the only way to do this is through documentation. However, in OOP, access modifiers not only indicate the primacy of certain functions over others, they enforce it program- matically. They implement language constraints to ensure that “subroutines” are never called directly. Properly constructed classes are self-documenting and self-regulating.
In the situation just described, the need to document a code library arises because it’s used in a collaborative environment; the exact same circum- stance accounts for the existence of access modifiers. One of the assumptions of OOP is that it is conducted within an interactive context with access modi- fiers defining the ways of interacting. This is one of the important differences between OOP and procedural programming. Access modifiers provide the rules for using a class and this syntactically defined “etiquette” is commonly referred to as an interface. By providing an interface, there is less need to rely on documentation and on user programmers “doing the right thing.”
Documenting code libraries is important because libraries get reused;
access modifiers matter for exactly the same reason—they facilitate reuse.

Object Reuse and Inheritance

In a biological sense, a child inherits genes from its parents, and this genetic material conditions the appearance and behavior of the child. In OOP the meaning of inheritance is analogous—it is the ability to pass along charac- teristics and behavior. At first this feature of OOP may seem somehow magical, but really inheritance is just a technique for reusing code—much the way you might include a library of functions in procedural programming.

simply use it and benefit from the predefined behavior. Inheritance comes into play when a class doesn’t do quite what you want. This situation is not much different from adding functions to an existing code library. Through inheritance you can take advantage of existing behavior but also graft on any additional capabilities you need. For example, if you know that you want to create a Blue jay class and none exists, you can use an existing Bird class by inheriting from it, then modify it to suit your specific situation.
When one class forms the basis for a new class, as a Bird class might for a Blue jay class, the original class is often referred to as the base (or parent) class. For obvious reasons, a class derived from another class is called a derived class or a child class.

Multiple Inheritance

In nature, multiple inheritance is the norm, but in the world of OO PHP, an object can have only one parent class. The creators of PHP 5 rejected the idea of multiple inheritance for classes. To see why, let’s use the Bird class again to show what multiple inheritance is and how it can lead to problems. If you wanted to create a Whooping crane class, it would make sense to derive this class from the Bird class. Suppose you also have an Endangered species class. Multiple inheritance would allow you to create a Whooping crane class from a combination of these two classes. This would seem to be an excellent idea until you realize that both classes define an eating behavior. Which one should you prefer? Awkward situations like this highlight the disadvantages of multiple inheritance. With single inheritance this kind of situation never arises.

Having Your Cake and Eating It Too

Single inheritance offers a simpler and more straightforward approach, but there are times when you may wish to combine behaviors from different classes. A whooping crane is both a bird and endangered. It doesn’t make sense to build one of these classes from scratch every time you want this combination. Is there a way of combining different classes and avoiding the problem of overlapping behavior?
PHP solves this problem by introducing the concept of an interface. In this context, interface means a class with no data members that is made up only of functions that lack an implementation (function prototypes with no bodies). Any class that inherits from an interface must implement the missing function body. If Endangered species were an interface rather than a class, having more than one eating function wouldn’t matter. The method defini- tion in the Bird class would act as the implementation of the interface function. In this way interfaces avoid the problem of defining the same function twice.

NOTE Because PHP does not require function prototyping, you may be unfamiliar with this concept. A function prototype is the declaration of a function name and parameters prior to its use—the function signature, if you like.

A class may inherit from only one class, but because interfaces lack an implementation any number of them may be inherited. In true PHP fashion, interfaces contribute to a powerful but flexible programming language. (You’ll see how useful interfaces are in Chapter 10, where we add the
built-in interface Iterator to a database class.)
Interfaces can be described as abstract because they always require an implementation. Because they are abstract, interfaces bear more resemblance to templates than classes do. Unlike classes, they can never be used “as is”; they are only meaningful in the context of inheritance. Because interfaces lack an implementation they can act only as a model for creating a derived class.

Where to Go from Here

We’ve touched on three topics central to OOP: classes, access modifiers, and inheritance. Classes define objects, access modifiers determine how objects can be used, and inheritance makes it easy to adapt objects for different cir- cumstances. I’ve emphasized the ways in which procedural programming is like OOP with a view to easing the transition to an OO approach, but I’ve also shown important differences. A data type like a class, which incorporates functions, is unlike anything encountered in procedural programming. Addi- tionally, OOP provides access modifiers to control how an object may be used. Instead of relying on documentation and a disciplined approach, OOP incorporates constraints into the language.
The next chapter discusses the differences between PHP 4 and PHP 5. This will be particularly useful for people already familiar with the OO capa- bilities of PHP 4 who want an overview of the improvements.

0 comments: