34 Emulating object technology in non-O-O environments ran.Cobol.Paseal,C.Basic.PLI and even assembly anguage still accout for large part of the software being written or updated today.Clearly,a project using one of these languages will not be able to draw the full benefits ofobject technology,as this would require a notation such as the one we have studied in this book,and the supporting compiler,environment and libraries.But people who are required to use pre-O-O tools, often because of non-technical constraints,can still gain inspiration from object technology and use some of its concepts to improve the quality of their software development. This chapter presents the techniques of object emulation that may enable you to approximate some of object technology.It will particularly examine the case of Fortran, Pascal and C.(Ada and other encapsulation languages were discussed in the preceding chapter;the following one covers O-O languages such as Simula,Smalltalk,Objective-C, C++and Java.)This presentation will be directly applicable if you must use one of these languages.But it extends further: If you use another non-O-O language not on this list,such as Basic or Cobol,you should not have too much trouble transposing the concepts. Even if you are able to use an O-O language,the following discussion can give you a better grasp of the innovations of object technology and of the supporting implementation techniques(which often make use,internally,of older languages). 34.1 LEVELS OF LANGUAGE SUPPORT In assessing how programming languages succeed in supporting object-oriented concepts, we may distinguish three broad categories(ignoring the lowest level,mostly containing assembly languages,which does not even support a routine construct): The functional level comprises languages whose unit ofdecomposition is theroutine, a functional abstraction capturing a processing step.Data abstraction is handled,if at all,through definitions of data structures,either local to a routine or global. Languages at the encapsulation level provide a way to group a set of routines and data declarations in a syntactical unit,called a module or package;typically each unit can be compiled separately.This was discussed in some detail for Ada
34 Emulating object technology in non-O-O environments Fortran, Cobol, Pascal, C, Basic, PL/I and even assembly language still account for a large part of the software being written or updated today. Clearly, a project using one of these languages will not be able to draw the full benefits of object technology, as this would require a notation such as the one we have studied in this book, and the supporting compiler, environment and libraries. But people who are required to use pre-O-O tools, often because of non-technical constraints, can still gain inspiration from object technology and use some of its concepts to improve the quality of their software development. This chapter presents the techniques of object emulation that may enable you to approximate some of object technology. It will particularly examine the case of Fortran, Pascal and C. (Ada and other encapsulation languages were discussed in the preceding chapter; the following one covers O-O languages such as Simula, Smalltalk, Objective-C, C++ and Java.) This presentation will be directly applicable if you must use one of these languages. But it extends further: • If you use another non-O-O language not on this list, such as Basic or Cobol, you should not have too much trouble transposing the concepts. • Even if you are able to use an O-O language, the following discussion can give you a better grasp of the innovations of object technology and of the supporting implementation techniques (which often make use, internally, of older languages). 34.1 LEVELS OF LANGUAGE SUPPORT In assessing how programming languages succeed in supporting object-oriented concepts, we may distinguish three broad categories (ignoring the lowest level, mostly containing assembly languages, which does not even support a routine construct): • The functional level comprises languages whose unit of decomposition is the routine, a functional abstraction capturing a processing step. Data abstraction is handled, if at all, through definitions of data structures, either local to a routine or global. • Languages at the encapsulation level provide a way to group a set of routines and data declarations in a syntactical unit, called a module or package; typically each unit can be compiled separately. This was discussed in some detail for Ada
1100 EMULATING OBJECT TECHNOLOGY IN NON-O-O ENVIRONMENTS $34.2 Then we find object-oriented languages.This is not the place to be fussy about what exactly it takes to deserve this label-chapter 2 defined a set of criteria,and of course all of part C was devoted to analyzing O-O mechanisms in detail-,but we should at the very least expect some support for classes,inheritance,polymorphism and dynamic binding. For the second category,encapsulation languages,which supports a data See[Wegner1987刃 abstraction mechanism but no classes,inheritance,polymorphism or dynamic binding,you will find that the literature commonly uses the term object- based,introduced in an article by Peter Wegner.Because the English words based and oriented do not readily evoke the conceptual difference between encapsulation techniques and O-O languages,"object-based"is a little hard to justify,especially to newcomers.Although either terminology is acceptable once you have defined the conventions,I have in the end decided to stick here to the phrases "encapsulation languages"and"object-oriented languages", which more clearly conjure up the conceptual difference. While we are on the subject of terminology:the term "functional language"is ambiguous since other parts of the literature apply it to a class of languages,based on mathematical principles and often deriving directly or indirectly from Lisp,which use side-effect-free functions instead of imperative constructs such as procedures and assignments.To avoid any confusion,the present book always uses the term applicative to denote this programming style.The word function in our use of"functional language" is to be contrasted with object,not (as when "functional"is a synonym for "applicative") with procedure.(To make a confusing situation worse,it is quite common to see "procedural"taken to mean "not object-oriented"!There is,however,no basis for such terminology,“procedural'”normally means“imperative'”,as opposed to applicative,:all the common O-O languages,including the notation of this book,are quite procedural.) A general comment on O-O emulation.In its most basic form,object technology is "programming with abstract data types".You can apply a rudimentary form of the ideas, even at the functional level,by defining a set of strict methodological guidelines requiring every data access to go through routines.This assumes that you start from an object- oriented design that has defined ADTs and their features;then you will write a set of routines representing these features-put,remove,item,empty in our standard stack example-and require all client modules to go through these routines.This is a far cry from object technology proper,and can only work under the assumption that everyone in the team behaves;but,if you lack any kind of language support,it can be a start.We will call this technique the disciplinary approach. 34.2 OBJECT-ORIENTED PROGRAMMING IN PASCAL? Pascal,introduced in 1970 by Niklaus Wirth,has been for many years the dominant language for teaching introductory programming in computing science departments,and has influenced many of the subsequent language designs.Pascal is definitely a functional language in the sense just defined
1100 EMULATING OBJECT TECHNOLOGY IN NON-O-O ENVIRONMENTS §34.2 • Then we find object-oriented languages. This is not the place to be fussy about what exactly it takes to deserve this label — chapter 2 defined a set of criteria, and of course all of part C was devoted to analyzing O-O mechanisms in detail —, but we should at the very least expect some support for classes, inheritance, polymorphism and dynamic binding. For the second category, encapsulation languages, which supports a data abstraction mechanism but no classes, inheritance, polymorphism or dynamic binding, you will find that the literature commonly uses the term objectbased, introduced in an article by Peter Wegner. Because the English words based and oriented do not readily evoke the conceptual difference between encapsulation techniques and O-O languages, “object-based” is a little hard to justify, especially to newcomers. Although either terminology is acceptable once you have defined the conventions, I have in the end decided to stick here to the phrases “encapsulation languages” and “object-oriented languages”, which more clearly conjure up the conceptual difference. While we are on the subject of terminology: the term “functional language” is ambiguous since other parts of the literature apply it to a class of languages, based on mathematical principles and often deriving directly or indirectly from Lisp, which use side-effect-free functions instead of imperative constructs such as procedures and assignments. To avoid any confusion, the present book always uses the term applicative to denote this programming style. The word function in our use of “functional language” is to be contrasted with object, not (as when “functional” is a synonym for “applicative”) with procedure. (To make a confusing situation worse, it is quite common to see “procedural” taken to mean “not object-oriented”! There is, however, no basis for such terminology; “procedural” normally means “imperative”, as opposed to applicative; all the common O-O languages, including the notation of this book, are quite procedural.) A general comment on O-O emulation. In its most basic form, object technology is “programming with abstract data types”. You can apply a rudimentary form of the ideas, even at the functional level, by defining a set of strict methodological guidelines requiring every data access to go through routines. This assumes that you start from an objectoriented design that has defined ADTs and their features; then you will write a set of routines representing these features — put, remove, item, empty in our standard stack example — and require all client modules to go through these routines. This is a far cry from object technology proper, and can only work under the assumption that everyone in the team behaves; but, if you lack any kind of language support, it can be a start. We will call this technique the disciplinary approach. 34.2 OBJECT-ORIENTED PROGRAMMING IN PASCAL? Pascal, introduced in 1970 by Niklaus Wirth, has been for many years the dominant language for teaching introductory programming in computing science departments, and has influenced many of the subsequent language designs. Pascal is definitely a functional language in the sense just defined. See [Wegner 1987]
$34.2 OBJECT-ORIENTED PROGRAMMING IN PASCAL? 1101 Pascal proper How much of the object-oriented approach can you implement in Pascal? Not much.The Pascal program structure is based on a completely different paradigm.A Pascal program consists of a sequence of paragraphs,appearing in an immutable order:labels,constants,types,variables,routines (procedures and functions), and executable instructions.The routines themselves have the same structure,recursively. This simple rule facilitates one-pass compilation.But it dooms any attempt at using O-O techniques.Consider what it takes to implement an ADT,such as the standard example of stacks represented by arrays:a few constants such as the array size,one or a few types such as the record type describing the stack implementation,a few variables such as the pointer to the stack top,and a few routines representing the operations on the abstract data type.In Pascal,these elements will be scattered all over the program:all the constants for various abstract data types together,all the types together and so on. “Linguistic Modular The resulting program structure is the opposite of O-O designs.Using Pascal would Ums”page53. contradict the Linguistic Modular Units principle,which expresses that any modular policy you choose must be supported by the available language constructs,for fear of damaging composability,decomposability and other modularity requirements. So if we take Pascal as defined by its official standard,there is little we can do to apply O-O techniques this language beyond what was called the disciplinary approach above:imposing a strict methodological rule for data accesses. Modular extensions of Pascal Beyond standard Pascal,many commercially available versions remove the restrictions on the order of declarations and include support for some form of module beyond the routine, including separate compilation.Such modules may contain more than one routine, together with associated constants,types and routines.The resulting languages and products,more flexible and powerful than Pascal,are Pascal only by name;they are not standardized,and in fact resemble more an encapsulation language such as Modula-2 or Ada,to which the applicable discussion is that of the preceding chapter. Object-oriented extensions of Pascal Over the years a number of companies have offered object-oriented extensions of Pascal, loosely known as"Object Pascal".Two are particularly significant: Apple's version,originating from a language originally called Clascal and used for some of the software in Apple's Macintosh and its Lisa predecessor. Borland's version of Pascal,most recently adapted as the programming language for Borland's Delphi environment. The preceding discussion does not really apply to such languages since-even more than with the modular extensions-their connection to the original Pascal is essentially their name,syntactic style,and statically typed approach.Borland Pascal,in particular,is an O-O language with exception handling.It does not,however,support any of the mechanisms of genericity,assertions,garbage collection and multiple inheritance
§34.2 OBJECT-ORIENTED PROGRAMMING IN PASCAL? 1101 Pascal proper How much of the object-oriented approach can you implement in Pascal? Not much. The Pascal program structure is based on a completely different paradigm. A Pascal program consists of a sequence of paragraphs, appearing in an immutable order: labels, constants, types, variables, routines (procedures and functions), and executable instructions. The routines themselves have the same structure, recursively. This simple rule facilitates one-pass compilation. But it dooms any attempt at using O-O techniques. Consider what it takes to implement an ADT, such as the standard example of stacks represented by arrays: a few constants such as the array size, one or a few types such as the record type describing the stack implementation, a few variables such as the pointer to the stack top, and a few routines representing the operations on the abstract data type. In Pascal, these elements will be scattered all over the program: all the constants for various abstract data types together, all the types together and so on. The resulting program structure is the opposite of O-O designs. Using Pascal would contradict the Linguistic Modular Units principle, which expresses that any modular policy you choose must be supported by the available language constructs, for fear of damaging composability, decomposability and other modularity requirements. So if we take Pascal as defined by its official standard, there is little we can do to apply O-O techniques this language beyond what was called the disciplinary approach above: imposing a strict methodological rule for data accesses. Modular extensions of Pascal Beyond standard Pascal, many commercially available versions remove the restrictions on the order of declarations and include support for some form of module beyond the routine, including separate compilation. Such modules may contain more than one routine, together with associated constants, types and routines. The resulting languages and products, more flexible and powerful than Pascal, are Pascal only by name; they are not standardized, and in fact resemble more an encapsulation language such as Modula-2 or Ada, to which the applicable discussion is that of the preceding chapter. Object-oriented extensions of Pascal Over the years a number of companies have offered object-oriented extensions of Pascal, loosely known as “Object Pascal”. Two are particularly significant: • Apple’s version, originating from a language originally called Clascal and used for some of the software in Apple’s Macintosh and its Lisa predecessor. • Borland’s version of Pascal, most recently adapted as the programming language for Borland’s Delphi environment. The preceding discussion does not really apply to such languages since — even more than with the modular extensions — their connection to the original Pascal is essentially their name, syntactic style, and statically typed approach. Borland Pascal, in particular, is an O-O language with exception handling. It does not, however, support any of the mechanisms of genericity, assertions, garbage collection and multiple inheritance. “Linguistic Modular Units”, page 53
1102 EMULATING OBJECT TECHNOLOGY IN NON-O-O ENVIRONMENTS $34.3 34.3 FORTRAN FORTRAN should virtually eliminate coding and debugging Cited in [Wexelblat FORTRAN Preliminary Report,IBM,November 1954 1981]. The oldest surviving programming language,Fortran remains widely used for scientific The official name is computation.Shockingly perhaps for people who went on from it to such "structured" FORTRAN,although the less obtrusive languages as Pascal,you can in fact get a little more O-O frills in Fortran,although this is form is commonly partly thanks to facilities that may be considered low-level and were intended for other goals. used too. Some context Fortran was initially designed,as a tool for programming the IBM 704,by an IBM team under John Backus (later also instrumental in the description of Algol),with a first general release in 1957.Fortran II followed,introducing subroutines.Fortran IV solidified the language in 1966(Fortran IIL,704-specific,was not widely distributed),and was standardized by ANSI The next revision process led to Fortran 77,actually approved in 1978,with better control structures and some simplifications.An even longer revision yielded Fortran 90 and Fortran 95,which have been diversely met and have not quite replaced their predecessors. For most people with a computing science degree earned after the First World War, Fortran is old hat,and they would rather be caught reading the Intel 4044 User's Manual than admit they know anything about FORMAT and arithmetic /F instructions.In reality, however,quite a few programmed in Fortran at some stage,and many other people who are programmers by any objective criterion,even if their business card reads"theoretical physicist","applied mathematician","mechanical engineer"or even,in a few cases, "securities analyst",use Fortran as their primary tool day in and day out.Fortran remains in common use not only for maintaining old software but even for starting new projects. To the outsider it sometimes seems that scientific programming-the world of Fortran-has remained aloof from much of the evolution in software engineering.This is partly true,partly not.The low level of the language,and the peculiar nature of scientific computing (software produced by people who,although scientists by training,often lack formal software education),have resulted in some software of less than pristine quality. But some of the best and most robust software also comes from that field,including advanced simulations of extremely complex processes and staggering tools for scientific visualization.Such products are no longer limited to delicate but small numerical algorithms;like their counterparts in other application areas,they often manipulate complex data structures,rely on database technology,include extensive user interface components.And,surprising as it may seem,they are still often written in Fortran. The COMMON technique A Fortran system is made of a main program and a number of routines(subroutines or functions).How can we provide a semblance of data abstraction? The usual technique is to represent the data through a so-called COMMON block,a Fortran mechanism for making data accessible to any routine that cares to want it,and to implement each of the associated exported features(such as put etc.for stacks)through a separate routine.Here for example is a sketch of a put routine for a stack of real numbers:
1102 EMULATING OBJECT TECHNOLOGY IN NON-O-O ENVIRONMENTS §34.3 34.3 FORTRAN FORTRAN should virtually eliminate coding and debugging FORTRAN Preliminary Report, IBM, November 1954 The oldest surviving programming language, Fortran remains widely used for scientific computation. Shockingly perhaps for people who went on from it to such “structured” languages as Pascal, you can in fact get a little more O-O frills in Fortran, although this is partly thanks to facilities that may be considered low-level and were intended for other goals. Some context Fortran was initially designed, as a tool for programming the IBM 704, by an IBM team under John Backus (later also instrumental in the description of Algol), with a first general release in 1957. Fortran II followed, introducing subroutines. Fortran IV solidified the language in 1966 (Fortran III, 704-specific, was not widely distributed), and was standardized by ANSI. The next revision process led to Fortran 77, actually approved in 1978, with better control structures and some simplifications. An even longer revision yielded Fortran 90 and Fortran 95, which have been diversely met and have not quite replaced their predecessors. For most people with a computing science degree earned after the First World War, Fortran is old hat, and they would rather be caught reading the Intel 4044 User’s Manual than admit they know anything about FORMAT and arithmetic IF instructions. In reality, however, quite a few programmed in Fortran at some stage, and many other people who are programmers by any objective criterion, even if their business card reads “theoretical physicist”, “applied mathematician”, “mechanical engineer” or even, in a few cases, “securities analyst”, use Fortran as their primary tool day in and day out. Fortran remains in common use not only for maintaining old software but even for starting new projects. To the outsider it sometimes seems that scientific programming — the world of Fortran — has remained aloof from much of the evolution in software engineering. This is partly true, partly not. The low level of the language, and the peculiar nature of scientific computing (software produced by people who, although scientists by training, often lack formal software education), have resulted in some software of less than pristine quality. But some of the best and most robust software also comes from that field, including advanced simulations of extremely complex processes and staggering tools for scientific visualization. Such products are no longer limited to delicate but small numerical algorithms; like their counterparts in other application areas, they often manipulate complex data structures, rely on database technology, include extensive user interface components. And, surprising as it may seem, they are still often written in Fortran. The COMMON technique A Fortran system is made of a main program and a number of routines (subroutines or functions). How can we provide a semblance of data abstraction? The usual technique is to represent the data through a so-called COMMON block, a Fortran mechanism for making data accessible to any routine that cares to want it, and to implement each of the associated exported features (such as put etc. for stacks) through a separate routine. Here for example is a sketch of a put routine for a stack of real numbers: Cited in [Wexelblat 1981]. The official name is FORTRAN, although the less obtrusive form is commonly used too
§34.3 FORTRAN 1103 A C at the first SUBROUTINE RPUT (X) position on a line REAL X introduces a C CO7m171e71. C PUSH X ON TOP OF REAL STACK COMMON /STREP/TOP,STACK (2000) INTEGER TOP REAL STACK TOP=TOP+1 STACK (TOP)=X RETURN END This version does not have any overflow control;clearly it should be updated to test for TOP going over the array size.(The next version will correct this.)The function to retum the top element is INTEGER FUNCTION RITEM C C TOP ELEMENT OF REAL STACK C COMMON /STREP/TOP,STACK (2000) INTEGER TOP REAL STACK RITEM=STACK(TOP) RETURN END which would similarly need to test for underflow (empty stack).REMOIE and other features will follow the same pattern.What unites the different routines,making sure that they access the same data,is simply the name of the common block,STREP.(It is in fact possible,in different routines,to pretend that the same common block contains data of different types and sizes if the total memory occupied somehow coincides,although in a family-oriented book like this one it is probably preferable to avoid going into details that might not be entirely suitable for the younger members of the audience). The limitations are obvious:this implementation describes one abstract object (one particular stack of reals),not an abstract data type of which the software can create arbitrarily many instances at run time,as with a class.The Fortran world is very static:you must dimension all the arrays(here to 2000,a number picked arbitrarily).Because there is no genericity,you should in principle declare a new set of routines for each type of stack;hence the names RPUT and R/TEM,where the R stands for Real.One can work around some of these problems,but not without considerable effort
§34.3 FORTRAN 1103 SUBROUTINE RPUT (X) REAL X C C PUSH X ON TOP OF REAL STACK C COMMON /STREP/ TOP, STACK (2000) INTEGER TOP REAL STACK C TOP = TOP + 1 STACK (TOP) = X RETURN END This version does not have any overflow control; clearly it should be updated to test for TOP going over the array size. (The next version will correct this.) The function to return the top element is INTEGER FUNCTION RITEM C C TOP ELEMENT OF REAL STACK C COMMON /STREP/ TOP, STACK (2000) INTEGER TOP REAL STACK RITEM = STACK (TOP) RETURN END which would similarly need to test for underflow (empty stack). REMOVE and other features will follow the same pattern. What unites the different routines, making sure that they access the same data, is simply the name of the common block, STREP. (It is in fact possible, in different routines, to pretend that the same common block contains data of different types and sizes if the total memory occupied somehow coincides, although in a family-oriented book like this one it is probably preferable to avoid going into details that might not be entirely suitable for the younger members of the audience). The limitations are obvious: this implementation describes one abstract object (one particular stack of reals), not an abstract data type of which the software can create arbitrarily many instances at run time, as with a class. The Fortran world is very static: you must dimension all the arrays (here to 2000, a number picked arbitrarily). Because there is no genericity, you should in principle declare a new set of routines for each type of stack; hence the names RPUT and RITEM, where the R stands for Real. One can work around some of these problems, but not without considerable effort. A C at the first position on a line introduces a comment