Object-Oriented Programming and MacApp
Welcome to the world of object-oriented programming (OOP) and MacApp, Apple's object-oriented Macintosh application framework. Long experience at Apple and elsewhere has shown that OOP offers substantial advantages over traditional functional-programming techniques, particularly for the kind of complex applications today's users have come to expect. Because we believe that OOP will be the programming model for future generations of computers, we will continue our long-term commitment to OOP. We think that when you take a look at the future direction of application development, you will recognize that OOP represents a better choice than procedural programming.
The information in this document provides a brief introduction to OOP and MacApp, and includes a description of the documentation and tools you'll need to get started. We encourage you to take advantage of the opportunities OOP has created.
Object-Oriented Programming Versus Procedural Programming
Compared with traditional procedural programming, object-oriented programming speeds software development and makes programs easier to create, understand, and maintain. Four concepts are key to the benefits of OOP: object, class, inheritance, and polymorphism. Let's look at each one.
Consider a familiar object; for example, a light bulb. It has fixed states (wattage rating, mass, and bulb type), variable states (on or off), and behavior (heat and light production, current flow). Behavior and state are inextricably intertwined in real-world objects. Yet modern CPUs and traditional programming languages treat the computer analogs of behavior and state - code and data - as inherently separate. This separation complicates the design, debugging, and maintenance of software. We are all familiar with apparently innocent modifications to a data structure that break procedures throughout a program.
Object-oriented programming languages explicitly mimic the real world by linking data and the procedures that manipulate that data into what are called objects. A light-bulb object, for instance, would have variables for its state and procedures for computing heat, current flow, and light output. This encapsulation of data and code minimizes and localizes the procedures that rely upon detailed knowledge of an object's data structures. Consequently, object-oriented programs are easier to understand and to maintain.
The object-oriented programmer describes different types of objects, including the appropriate linkage of data and procedures, by defining classes. A class specifies the structure of the data for all individual objects of the class, as does a Pascal RECORD or C struct. Unlike records or structs, however, each class also specifies the procedures unique to it. Although each individual object will normally have its own data, all objects of a given class share the same set of procedures.
The various types of real-world objects in an application domain become separate classes in the program. These classes need to share behavior because the corresponding types of real-world objects often share behavior. For instance, a taxi is a kind of car, which is a kind of vehicle. Therefore a taxi shares most of the behavior of any vehicle and almost all of the behavior of a car. Relationships such as these can be expressed naturally in OOP by making the more specialized class a subclass of the more general class. The sharing of behavior arises because a subclass inherits all of the data and procedures of its superclass. So if taxi is a subclass of car, then, with no further effort on the part of the programmer, taxi objects would already have all the structure and behavior of car objects. The programmer of the taxi class presumably would add new data items (two-way radios, fare meters, and so on) and new procedures (computing fares, for example). Procedures already implemented by cars may be modified or overridden (taxis may use special lanes at airports or always have broken air conditioners). But most of the structure and code of the car superclass is effortlessly reused by the taxi subclass. This reuse of inherited code simplifies maintenance.
In traditional procedural programming, the code to be executed at every point in the program is specified exactly by the order of procedure calls. When a procedural language compiler encounters a procedure call, it knows precisely what code to invoke. But in OOP, a subclass may override a procedure implemented by its superclass. In that case, the method (or procedure) in the subclass and the superclass have the same name. The actual code to be executed depends on the class of the object on which it is supposed to act. This flexible binding of code with method names is called polymorphism.
Pascal or C programmers routinely use a limited form of polymorphism: Arithmetic operators such as the plus operator (+) invoke different code for integers than for floats. But this primitive polymorphism is hard-coded in the compiler, usually limited to a few mathematical operators, and cannot be extended by the programmer. By giving the programmer control of polymorphism (hence the ability to selectively override and enhance existing behavior in new subclasses), OOP makes code reuse practical and adds to the flexibility and mutability of the program.
Object-Oriented Programming Libraries and Tools
Object-oriented programming requires a mature class library and specialized programming tools, in addition to an OOP language.
Classes, inheritance, and polymorphism provide the opportunity for code reuse. Object-oriented class libraries provide the code to reuse. Mature class libraries turn the promise of OOP into successful practice. These libraries, however, must be carefully designed and well tested. With wide reuse, every weak spot (whether a boundary condition or careless assumption) will be tested. Designing classes for maximum reusability also requires insight into how best to generalize the classes. Good class hierarchies, like those of Smalltalk or MacApp, have grown by natural selection over a period of years. Much of the advertised productivity gain of OOP stems from the use of such libraries. Once the programmer learns a library, much of the functionality of each new program is borrowed or inherited from existing library code. Rather than measuring programming productivity in lines-per-day of new code, the experienced OOP programmer takes pride in how little new code is needed.
Familiar development tools such as editors and debuggers have evolved to meet the needs of traditional procedural programming. The special features of OOP place additional demands on these development tools. The distribution of behavior among classes and the sharing of code fostered by inheritance require a tool for rapidly browsing code by class and method name. Typical editors are clumsy for such browsing. The distribution of most data amongst a variety of objects requires an object inspector tool for examining the state of active objects that "knows" the structure of the objects and can display that data in a meaningful form. Traditional tools for displaying individual memory locations in HEX are tedious at best, and an object-oriented debugger must be aware of classes and method invocations as well as the structure of objects. Class libraries that offer classes for construction of windows and dialogs also require a graphical direct-manipulation layout tool for easy construction of those visual interfaces. MacApp offers all of these.
MacApp version 2.0B9 is the latest beta release of Apple's second-generation object-oriented Macintosh application framework. MacApp offers a mature object-oriented class library that is ideal for programmers who wish to maximize their productivity as they develop robust, user-friendly, commercial Macintosh applications.
MacApp helps you work more productively by allowing you to program in a style well suited to Macintosh applications. Your application can inherit the behavior of a standard Macintosh application directly from MacApp code; you can then override the parts you wish to customize. With MacApp and less than a page of your own code, you can have a complete Macintosh application that creates windows, interprets mouse clicks, handles desk accessories, prints files, and supports every other standard feature a Macintosh application is likely to have.
The applications you create with MacApp can run on any Macintosh Plus, Macintosh SE, or Macintosh II computer. If the code you add follows Apple's compatibility guidelines, your applications will run on both the Macintosh and A/UX operating systems (including MultiFinder compatibility on the Macintosh OS).
MacApp is widely used for in-house development by firms such as GTE Government Systems, Peat Marwick & Main, and Arthur Andersen. It has been used by companies such as Odesta, Activision, and Olduvai to develop commercial applications for networking and communications, accounting, report generation, geographical data display, CAD, optical character recognition, knowledge engineering, and geology.