K. Cooper, L. Torczon - Engineering a Compiler (2011 - 2nd edition) (798440), страница 73
Текст из файла (страница 73)
Unfortunately, the term object-oriented hasbeen given so many different meanings and implementations that it has cometo signify a wide range of language features and programming paradigms.As we shall see, not all ools can be compiled, in the traditional sense ofa translation that finalizes all of the details about the executable program.Features of some ools create name spaces that cannot be understood untilruntime. Implementations of these languages rely on runtime mechanismsthat run from interpretation to runtime compilation (so-called just-in-timecompilers or jits).
Because interpreters and jits use many of the same structures as a compiler, we describe the problem as it might be implemented ina traditional compiler.From the compiler’s perspective, ools reorganize the program’s name space.Most ools retain the procedure-oriented lexical scoping conventions ofan all for use within procedural code. They augment this classic namingscheme with a second set of conventions for naming, one organized aroundthe layout of data—specifically, the definitions of objects. This data-centricnaming discipline leads to a second hierarchy of scopes and a second mechanism for resolving names—that is, for mapping a source-language name intoa runtime address so that the compiled code can access the data associatedwith that name.Just-in-time compilerSchemes that perform some of the tasks of atraditional compiler at runtime are often calledjust-in-time compilers or JITs.In a JIT, compile time becomes part of runtime,so JITs place an emphasis on compile-timeefficiency.286 CHAPTER 6 The Procedure AbstractionTERMINOLOGY FOR OBJECT-ORIENTED LANGUAGESThe diversity of object-oriented languages has led to some ambiguity inthe terms that we use to discuss them.
To make the discussion in thischapter concrete, we will use the following terms:1. Object An object is an abstraction with one or more members. Thosemembers can be data items, code that manipulates those data items,or other objects. An object with code members is a class. Each objecthas internal state—data whose lifetimes match the object’s lifetime.2. Class A class is a collection of objects with the same abstract structureand characteristics. A class defines the set of data members in eachinstance of the class and defines the code members (methods) that arelocal to that class. Some methods are public, or externally visible,others are private, or invisible outside the class.3. Inheritance Inheritance refers to a relationship among classes thatdefines a partial order on the name scopes of classes. Each class mayhave a superclass from which it inherits both code and data members.If a is the superclass of b, b is a subclass of a.
Some languages allow aclass to have multiple superclasses.4. Receiver Methods are invoked relative to some object, called themethod’s receiver. The receiver is known by a designated name, suchas this or self, inside the method.The complexity and the power of an OOL arise, in large part, from theorganizational possibilities presented by its multiple name spaces.The syntax and terminology used to specifysubclasses varies between languages. In Java,a subclass extends its superclass, while in C++, asubclass is derived from its superclass.Inheritance imposes an ancestor relation on the classes in an application.Each class has, by declaration, one or more parent classes, or superclasses.Inheritance changes both the name space of the application and the mappingof method names to implementations.
If α is a superclass of β, then β isa subclass of α and any method defined in α must operate correctly on anobject of class β, if it is visible in β. The converse is not true; a methoddeclared in class β cannot be applied to an object of its superclass α, as themethod from β may need fields present in an object of class β that are absentfrom an object of class α.VisibilityWhen a method runs, it can reference names defined in multiple scope hierarchies.
The method is a procedure, with its own name space defined by theset of lexical scopes in which it is declared; the method can access names inthose scopes using the familiar conventions defined for alls. The methodwas invoked relative to some receiver; it can access that object’s own members. The method is defined in the receiver’s class. The method can access6.3 Name Spaces 287the members of that class and, by inheritance, of its superclasses. Finally,the program creates some global name space and executes in it. The runningmethod can access any names that are contained in that global name space.To make these issues concrete, consider the abstracted example shown inFigure 6.6. It defines a class, Point, of objects with integer fields x and yand methods draw and move. ColorPoint is a subclass of Point that extendsPoint with an additional field c of type Color.
It uses Point’s method formove, overrides its method for draw and defines a new method test thatperforms some computation and then invokes draw. Finally, class C defineslocal fields and methods and uses ColorPoint.Now, consider the names that are visible inside method m of class C. Methodm maps x and y to their declarations in C. It expressly references the classnames Point and ColorPoint. The assignment y = p.x takes its right-handside from the field x in the object p, which p has by inheritance from classPoint.
The left-hand side refers to m’s local variable y. The call to drawmaps to the method defined in ColorPoint. Thus, m refers to definitionsfrom all three classes in the example.class Point {public int x, y;public void draw() { ... };public void move() { ... };}class ColorPoint extends Point {// inherits x, y, & move()Color c;// local field of ColorPointpublic void draw() { ...
};// hide Point’s draw()public void test() { ...; draw(); };// local method}class C {int x, y;public void m() {// local fields// local methodint y;// local variable of mPoint p = new ColorPoint();// uses ColorPoint and, byy = p.x// inheritance, Pointp.draw()}}n FIGURE 6.6 Definitions for Point and ColorPoint.288 CHAPTER 6 The Procedure AbstractionTo translate this example, the compiler must track the hierarchy of namesand scopes established both by the scope rules inside methods and classesand by the hierarchy of classes and superclasses established by extends.Name resolution in this environment depends on both the details of the codedefinitions and the class structure of the data definitions.
To translate an ool,the compiler needs to model both the name space of the code and the namespaces associated with the class hierarchy. The complexity of that modeldepends on details of the specific ool.In Java, public makes a name visibleeverywhere while private makes the namevisible only within its own class.To add a final complication, some ools provide attributes for individualnames that change their visibility.
For example, a Java name can have theattributes public or private. Similarly, some ools provide a mechanism toreference names obscured by nesting. In c++, the :: operator allows the codeto name a scope while in Java the programmer can use a fully qualified name.Naming in the Class HierarchyThe class hierarchy defines a set of nested name scopes, just as a set of nestedprocedures and blocks does in an all.
In an all, lexical position defines therelationship between those name scopes—if procedure d is declared insideprocedure c, then d’s name space is nested inside c’s name space. In an ool,the class declarations can be lexically disjoint and the subclass relation isspecified by explicit declarations.Direct superclassIf class α extends β, then β is α’s directsuperclass. If β has a superclass γ , then γ is, bytransitivity, a superclass of α, but it is not α’sdirect superclass.To find the declaration of a name, the compiler must search the lexical hierarchy, the class hierarchy, and the global name space. For a name x in amethod m, the compiler first searches the lexical scopes that surround thereference in m.