
- •New to the Tenth Edition
- •Preface
- •Acknowledgments
- •About the Author
- •Contents
- •1.1 Reasons for Studying Concepts of Programming Languages
- •1.2 Programming Domains
- •1.3 Language Evaluation Criteria
- •1.4 Influences on Language Design
- •1.5 Language Categories
- •1.6 Language Design Trade-Offs
- •1.7 Implementation Methods
- •1.8 Programming Environments
- •Summary
- •Problem Set
- •2.1 Zuse’s Plankalkül
- •2.2 Pseudocodes
- •2.3 The IBM 704 and Fortran
- •2.4 Functional Programming: LISP
- •2.5 The First Step Toward Sophistication: ALGOL 60
- •2.6 Computerizing Business Records: COBOL
- •2.7 The Beginnings of Timesharing: BASIC
- •2.8 Everything for Everybody: PL/I
- •2.9 Two Early Dynamic Languages: APL and SNOBOL
- •2.10 The Beginnings of Data Abstraction: SIMULA 67
- •2.11 Orthogonal Design: ALGOL 68
- •2.12 Some Early Descendants of the ALGOLs
- •2.13 Programming Based on Logic: Prolog
- •2.14 History’s Largest Design Effort: Ada
- •2.15 Object-Oriented Programming: Smalltalk
- •2.16 Combining Imperative and Object-Oriented Features: C++
- •2.17 An Imperative-Based Object-Oriented Language: Java
- •2.18 Scripting Languages
- •2.19 The Flagship .NET Language: C#
- •2.20 Markup/Programming Hybrid Languages
- •Review Questions
- •Problem Set
- •Programming Exercises
- •3.1 Introduction
- •3.2 The General Problem of Describing Syntax
- •3.3 Formal Methods of Describing Syntax
- •3.4 Attribute Grammars
- •3.5 Describing the Meanings of Programs: Dynamic Semantics
- •Bibliographic Notes
- •Problem Set
- •4.1 Introduction
- •4.2 Lexical Analysis
- •4.3 The Parsing Problem
- •4.4 Recursive-Descent Parsing
- •4.5 Bottom-Up Parsing
- •Summary
- •Review Questions
- •Programming Exercises
- •5.1 Introduction
- •5.2 Names
- •5.3 Variables
- •5.4 The Concept of Binding
- •5.5 Scope
- •5.6 Scope and Lifetime
- •5.7 Referencing Environments
- •5.8 Named Constants
- •Review Questions
- •6.1 Introduction
- •6.2 Primitive Data Types
- •6.3 Character String Types
- •6.4 User-Defined Ordinal Types
- •6.5 Array Types
- •6.6 Associative Arrays
- •6.7 Record Types
- •6.8 Tuple Types
- •6.9 List Types
- •6.10 Union Types
- •6.11 Pointer and Reference Types
- •6.12 Type Checking
- •6.13 Strong Typing
- •6.14 Type Equivalence
- •6.15 Theory and Data Types
- •Bibliographic Notes
- •Programming Exercises
- •7.1 Introduction
- •7.2 Arithmetic Expressions
- •7.3 Overloaded Operators
- •7.4 Type Conversions
- •7.5 Relational and Boolean Expressions
- •7.6 Short-Circuit Evaluation
- •7.7 Assignment Statements
- •7.8 Mixed-Mode Assignment
- •Summary
- •Problem Set
- •Programming Exercises
- •8.1 Introduction
- •8.2 Selection Statements
- •8.3 Iterative Statements
- •8.4 Unconditional Branching
- •8.5 Guarded Commands
- •8.6 Conclusions
- •Programming Exercises
- •9.1 Introduction
- •9.2 Fundamentals of Subprograms
- •9.3 Design Issues for Subprograms
- •9.4 Local Referencing Environments
- •9.5 Parameter-Passing Methods
- •9.6 Parameters That Are Subprograms
- •9.7 Calling Subprograms Indirectly
- •9.8 Overloaded Subprograms
- •9.9 Generic Subprograms
- •9.10 Design Issues for Functions
- •9.11 User-Defined Overloaded Operators
- •9.12 Closures
- •9.13 Coroutines
- •Summary
- •Programming Exercises
- •10.1 The General Semantics of Calls and Returns
- •10.2 Implementing “Simple” Subprograms
- •10.3 Implementing Subprograms with Stack-Dynamic Local Variables
- •10.4 Nested Subprograms
- •10.5 Blocks
- •10.6 Implementing Dynamic Scoping
- •Problem Set
- •Programming Exercises
- •11.1 The Concept of Abstraction
- •11.2 Introduction to Data Abstraction
- •11.3 Design Issues for Abstract Data Types
- •11.4 Language Examples
- •11.5 Parameterized Abstract Data Types
- •11.6 Encapsulation Constructs
- •11.7 Naming Encapsulations
- •Summary
- •Review Questions
- •Programming Exercises
- •12.1 Introduction
- •12.2 Object-Oriented Programming
- •12.3 Design Issues for Object-Oriented Languages
- •12.4 Support for Object-Oriented Programming in Smalltalk
- •12.5 Support for Object-Oriented Programming in C++
- •12.6 Support for Object-Oriented Programming in Objective-C
- •12.7 Support for Object-Oriented Programming in Java
- •12.8 Support for Object-Oriented Programming in C#
- •12.9 Support for Object-Oriented Programming in Ada 95
- •12.10 Support for Object-Oriented Programming in Ruby
- •12.11 Implementation of Object-Oriented Constructs
- •Summary
- •Programming Exercises
- •13.1 Introduction
- •13.2 Introduction to Subprogram-Level Concurrency
- •13.3 Semaphores
- •13.4 Monitors
- •13.5 Message Passing
- •13.6 Ada Support for Concurrency
- •13.7 Java Threads
- •13.8 C# Threads
- •13.9 Concurrency in Functional Languages
- •13.10 Statement-Level Concurrency
- •Summary
- •Review Questions
- •Problem Set
- •14.1 Introduction to Exception Handling
- •14.2 Exception Handling in Ada
- •14.3 Exception Handling in C++
- •14.4 Exception Handling in Java
- •14.5 Introduction to Event Handling
- •14.6 Event Handling with Java
- •14.7 Event Handling in C#
- •Review Questions
- •Problem Set
- •15.1 Introduction
- •15.2 Mathematical Functions
- •15.3 Fundamentals of Functional Programming Languages
- •15.4 The First Functional Programming Language: LISP
- •15.5 An Introduction to Scheme
- •15.6 Common LISP
- •15.8 Haskell
- •15.10 Support for Functional Programming in Primarily Imperative Languages
- •15.11 A Comparison of Functional and Imperative Languages
- •Review Questions
- •Problem Set
- •16.1 Introduction
- •16.2 A Brief Introduction to Predicate Calculus
- •16.3 Predicate Calculus and Proving Theorems
- •16.4 An Overview of Logic Programming
- •16.5 The Origins of Prolog
- •16.6 The Basic Elements of Prolog
- •16.7 Deficiencies of Prolog
- •16.8 Applications of Logic Programming
- •Review Questions
- •Programming Exercises
- •Bibliography
- •Index

Programming Exercises |
521 |
7.Explain the dangers of C’s approach to encapsulation.
8.Why didn’t C++ eliminate the problems discussed in Problem 7?
9.What are the advantages and disadvantages of the Objective-C approach to syntactically distinguishing class methods from instance methods?
10.In what ways are the method calls in C++ more or less readable than those of Objective-C?
11.What are the arguments for and against the Objective-C design that method access cannot be restricted?
12.Why are destructors rarely used in Java but essential in C++?
13.What are the arguments for and against the C++ policy on inlining of methods?
14.Describe a situation where a C# struct is preferable to a C# class.
15.Explain why naming encapsulations are important for developing large programs.
16.Describe the three ways a client can reference a name from a namespace in C++.
17.The namespace of the C# standard library, System, is not implicitly available to C# programs. Do you think this is a good idea? Defend your answer.
18.What are the advantages and disadvantages of the ability to change objects in Ruby?
19.Compare Java’s packages with Ruby’s modules.
P R O G R A M M I N G E X E R C I S E S
1.Design an abstract data type for a matrix with integer elements in a language that you know, including operations for addition, subtraction, and matrix multiplication.
2.Design a queue abstract data type for float elements in a language that you know, including operations for enqueue, dequeue, and empty. The dequeue operation removes the element and returns its value.
3.Modify the C++ class for the abstract stack type shown in Section 11.4.2 to use a linked list representation and test it with the same code that appears in this chapter.
4.Modify the Java class for the abstract stack type shown in Section 11.4.4 to use a linked list representation and test it with the same code that appears in this chapter.
5.Write an abstract data type for complex numbers, including operations for addition, subtraction, multiplication, division, extraction of each of

522 |
Chapter 11 |
Abstract Data Types and Encapsulation Constructs |
the parts of a complex number, and construction of a complex number from two floating-point constants, variables, or expressions. Use Ada, C++, Java, C#, or Ruby.
6.Write an abstract data type for queues whose elements store 10-character names. The queue elements must be dynamically allocated from the heap. Queue operations are enqueue, dequeue, and empty. Use either Ada, C++, Java, C#, or Ruby.
7.Write an abstract data type for a queue whose elements can be any primitive type. Use Java 5.0, C# 2005, C++, or Ada.
8.Write an abstract data type for a queue whose elements include both a 20-character string and an integer priority. This queue must have the following methods: enqueue, which takes a string and an integer as parameters; dequeue, which returns the string from the queue that has the highest priority; and empty. The queue is not to be maintained in priority order of its elements, so the dequeue operation must always search the whole queue.
9.A deque is a double-ended queue, with operations adding and removing elements from either end. Modify the solution to Programming Exercise 7 to implement a deque.
10.Write an abstract data type for rational numbers (a numerator and a denominator). Include a constructor and methods for getting the numerator, getting the denominator, addition, subtraction, multiplication, division, equality testing, and display. Use Java, C#, C++, Ada, or Ruby.

12
Support for Object-
Oriented Programming
12.1Introduction
12.2Object-Oriented Programming
12.3Design Issues for Object-Oriented Languages
12.4Support for Object-Oriented Programming in Smalltalk
12.5Support for Object-Oriented Programming in C++
12.6Support for Object-Oriented Programming in Objective-C
12.7Support for Object-Oriented Programming in Java
12.8Support for Object-Oriented Programming in C#
12.9Support for Object-Oriented Programming in Ada 95
12.10 Support for Object-Oriented Programming in Ruby
12.11 Implementation of Object-Oriented Constructs
523

524 |
Chapter 12 Support for Object-Oriented Programming |
This chapter begins with a brief introduction to object-oriented programming, followed by an extended discussion of the primary design issues for inheritance and dynamic binding. Next, the support for object-oriented program-
ming in Smalltalk, C++, Objective-C, Java, C#, Ada 95, and Ruby is discussed. The chapter concludes with a short overview of the implementation of dynamic bindings of method calls to methods in object-oriented languages.
12.1 Introduction
Languages that support object-oriented programming now are firmly entrenched in the mainstream. From COBOL to LISP, including virtually every language in between, dialects that support object-oriented programming have appeared. C++, Objective-C, and Ada 95 support procedural and data-oriented programming, in addition to object-oriented programming. CLOS, an object-oriented version of LISP (Paepeke, 1993), also supports functional programming. Some of the newer languages that were designed to support object-oriented programming do not support other programming paradigms but still employ some of the basic imperative structures and have the appearance of the older imperative languages. Among these are Java and C#. Ruby is a bit challenging to categorize: It is a pure objectoriented language in the sense that all data are objects, but it is a hybrid language in that one can use it for procedural programming. Finally, there is the pure object-oriented but somewhat unconventional language: Smalltalk. Smalltalk was the first language to offer complete support for object-oriented programming. The details of support for object-oriented programming vary widely among languages, and that is the primary topic of this chapter.
This chapter relies heavily on Chapter 11. It is, in a sense, a continuation of that chapter. This relationship reflects the reality that object-oriented programming is, in essence, an application of the principle of abstraction to abstract data types. Specifically, in object-oriented programming, the commonality of a collection of similar abstract data types is factored out and put in a new type. The members of the collection inherit these common parts from that new type. This feature is inheritance, which is at the center of object-oriented programming and the languages that support it.
The other characterizing feature of object-oriented programming, dynamic binding of method calls to methods, is also extensively discussed in this chapter.
Although object-oriented programming is supported by some of the functional languages, for example, CLOS, OCaml, and F#, those languages are not discussed in this chapter.