|
Object Orientation |
|
This page is primarily for folks with no prior experience or training in object-oriented disciplines. "Prior experience or training" usually means experience or training in object-oriented programming, but might come from fields like cognitive psychology or artificial intelligence. These and many other fields have been influenced by, or have contributed to, the set of ideas called object orientation. Object orientation is one of the half dozen or so big, crucially important concepts to come out of the last few decades of computer and information technology. There are a few basic principles behind all object-oriented disciplines, with a broad range of applicability to fields such as programming, user interface design, and computer systems architectures. The key idea in any discussion of object-orientation is the notion of an object. This is a familiar word; take a moment and think about what it means in ordinary language. Some aspects of objects in the technical sense may at first appear strange, but analyzing how people perceive and think about objects will help to resolve the apparent problems. The object-oriented paradigm is most mature in the field of programming languages, but it was not primarily motivated by considerations of computer science. Its roots lie in efforts to make computers more comprehensible to people. Take a look at the characteristics of an object in the world as we might perceive it:
Two other aspects of objects are important. They stem from the relation between an object and its name:
Now consider some examples of what "objects" might be in the technical sense of object-oriented programming, object-oriented database, etc. Software modules, "things" that a programmer builds to provide some externally visible behavior or function, can be objects. In object-oriented programming (OOP), these modules encapsulate both programs and the data that makes an individual object unique. Things stored in OO databases are also objects. Without going into the technical details, these are not just passive data. They are more like the objects of OOP, except that they are persistent; they do not go away when the program ends. Things that users interact with in an interface to a computer system (folders, documents, etc.) can be objects, and can be external representations corresponding to OOP constructs. The general principles of object-orientation can be summarized as follows, based on the object properties discussed above:
Object-Oriented ProgrammingThe term "object-oriented" is most often seen in "object-oriented programming," or "OOP". Assuming you have programmed in some language such as COBOL, FORTRAN, or BASIC, here is a quick tour of how the general principles of object-orientation apply to programming. Encapsulation: The behavior of a program depends on both algorithms and data structures. In many programming languages, algorithms are coded into program modules (usually called procedures or functions), and data structures are represented separately. When a function is called, the programmer must pass the data structure it will operate on. An object-oriented program module - usually called simply "an object" - encapsulates both algorithms (code) and data. Other objects communicate with it by calling it or sending messages, and never see its internal structure. There is a function, or method, that gets executed for every message. Each object has instance variables that hold its unique, private data. Typically, these "objects" represent things in the real world. As an example, consider the object "my savings account" (in a bank). In real life I might want to deposit money into it, query the balance, withdraw, etc. So a programming object, mySavingsAccount, in a banking application might respond to the calls deposit(amount), queryBalance, withdraw(amount), etc. mySavingsAccount probably has an instance variable called balance, and others for account number, customer name, and so forth. Proponents of OOP believe that this kind of design for an application is easier to understand, and thus easier to implement and maintain. Software engineers will recognize this sort of thing as "information hiding," "separation of concerns," etc. The difference from classical software engineering or "structured" approaches, however, is that the problem has been decomposed into objects rather than functions. Composition: Expanding on the banking example, imagine an application for a full-service institution. It might provide FinancialPortfolio objects that contain, or are composed from, BankAccount, Stock, Bond, InsurancePolicy, etc., objects. (In a fully object-oriented system, an application is itself an object composed of other objects.) Classes: In the bank example, do we want to code each SavingsAccount object individually? After all, they differ only by a few parameters (account holder name, balance, etc.). Classes in an OOP system are templates or prototypes from which programs can create new objects. mySavingsAccount, for example, is an instance of the class SavingsAccount. Typically it would be created by sending a message to the class telling it to create a new object. The message would include arguments or parameters to initialize the object’s instance variables, in this case the customer name and balance: mySavingsAccount =
The ability to support classes is one of the differences between OOP languages, such as Smalltalk, C++, and Java, and "conventional" languages such as Pascal, PL/I, and C. Technically, the class holds the programming code for the object’s methods. The object itself holds its data (which is unique) but points to the class for methods (which all instances of the class share). Inheritance: Think about implementing a class called CheckingAccount. Clearly it has a lot in common with SavingsAccount; why not factor out the common behavior into a superclass BankAccount? There is a cognitive economy in thinking of savings accounts and checking accounts as special kinds of bank accounts; OOP systems mirror this by providing mechanisms to code the SavingsAccount and CheckingAccount classes not from scratch, but by specifying how they differ from a BankAccount superclass. The code in BankAccount defines all the common characteristics of savings and checking accounts. This results in code reuse and conceptual clarity. The example just given might be coded as BankAccount subclass: SavingsAccount.
The figure below is a "doughnut diagram" showing an object of class
SavingsAccount receiving the message
withdraw(50.00).
This figure is a common way of representing the inheritance relationship between different kinds of bank accounts:
Dynamic binding: Two other significant aspects of objects were mentioned, related to naming them. When we declare the name of a variable in a conventional programming language, we usually specify what type of object it refers to (for example, a real number, an integer, a character string, etc.). This can be a problem in object-oriented languages. Suppose I want to process all the accounts for a given bank in some way that does not depend on whether an account is savings or checking. It seems natural to declare a variable to be simply a BankAccount, and let it actually (when the program is running) be either a SavingsAccount or a CheckingAccount. In the terminology of programming languages, functions to be invoked by messages to the object referenced by the variable are dynamically bound at the time the program is run. (As opposed to being statically bound at the time the program is compiled.) If we do not know the type of an object, how can we (or the language compiler) figure out which method to execute when the object receives a message? In object-oriented languages, the answer is simple. Since operations are "packaged" into the object itself, it just does whatever is appropriate. Though this may sound strange to a programmer, notice that it is exactly how objects in the real world behave. Since object behavior in response to an action may take many forms, depending on the object, this is called polymorphism, from a Greek word meaning "many forms". Polymorphism makes OOPLs very flexible. New kinds of objects can be added without changing existing code, as long as they respond to the same messages. For example, imagine adding a MoneyMarketAccount class in the banking example. If MoneyMarketAccount objects respond to deposit, withdraw, etc., they can easily be added to existing applications. For specific examples of OO programming languages, see our pages on Smalltalk, C++, and Java. |