
- •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

Summary 517
methods and constants. So, modules are convenient for encapsulating libraries of related methods and constants, whose names are in a separate namespace so there are no name conflicts with other names in a program that uses the module. Modules are unlike classes in that they cannot be instantiated or subclassed and do not define variables. Methods that are defined in a module include the module’s name in their names. For example, consider the following skeletal module definition:
module MyStuff PI = 3.14159265
def MyStuff.mymethod1(p1)
...
end
def MyStuff.mymethod2(p2)
...
end
end
Assuming the MyStuff module is stored in its own file, a program that wants to use the constant and methods of MyStuff must first gain access to the module. This is done with the require method, which takes the file name in the form of a string literal as a parameter. Then, the constants and methods of the module can be accessed through the module’s name. Consider the following code that uses our example module, MyStuff, which is stored in the file named myStuffMod:
require 'myStuffMod'
...
MyStuff.mymethod1(x)
...
Modules are further discussed in Chapter 12.
S U M M A R Y
The concept of abstract data types, and their use in program design, was a milestone in the development of programming as an engineering discipline. Although the concept is relatively simple, its use did not become convenient and safe until languages were designed to support it.
The two primary features of abstract data types are the packaging of data objects with their associated operations and information hiding. A language may support abstract data types directly or simulate them with more general encapsulations.
Ada provides encapsulations called packages that can be used to simulate abstract data types. Packages normally have two parts: a specification, which

518 |
Chapter 11 |
Abstract Data Types and Encapsulation Constructs |
presents the client interface, and a body, which supplies the implementation of the abstract data type. Data type representations can appear in the package specification but be hidden from clients by putting them in the private clause of the package. The abstract type itself is defined to be private in the public part of the package specification. Private types have built-in operations for assignment and comparison for equality and inequality.
C++ data abstraction is provided by classes. Classes are types, and instances can be either stack or heap dynamic. A member function (method) can have its complete definition appear in the class or have only the protocol given in the class and the definition placed in another file, which can be separately compiled. C++ classes can have two clauses, each prefixed with an access modifier: private or public. Both constructors and destructors can be given in class definitions. Heap-allocated objects must be explicitly deallocated with delete.
As with C++, Objective-C data abstractions are classes. Classes are types and all are heap dynamic. Methods declarations must appear in interface sections of classes and method definitions must appear in implementation sections. Constructors are called initializers; they must be explicitly called. Instance variables can be private or public. Access to methods cannot be restricted. Method calls use syntax that is similar to that used by Smalltalk. Objective-C supports properties and access methods for properties can be furnished by the compiler.
Java data abstractions are similar to those of C++, except all Java objects are allocated from the heap and are accessed through reference variables. Also, all objects are garbage collected. Rather than having access modifiers attached to clauses, in Java the modifiers appear on individual declarations (or definitions).
C# supports abstract data types with both classes and structs. Its structs are value types and do not support inheritance. C# classes are similar to those of Java.
Ruby supports abstract data types with its classes. Ruby’s classes differ from those of most other languages in that they are dynamic—members can be added, deleted, or changed during execution.
Ada, C++, Java 5.0, and C# 2005 allow their abstract data types to be parameterized—Ada through its generic packages, C++ through its templated classes, and Java 5.0 and C# through their collection classes and interfaces and user-defined generic classes.
To support the construction of large programs, some contemporary languages include multiple-type encapsulation constructs, which can contain a collection of logically related types. An encapsulation may also provide access control to its entities. Encapsulations provide the programmer with a method of organizing programs that also facilitates recompilation.
C++, C#, Java, Ada, and Ruby provide naming encapsulations. For Ada and Java, they are named packages; for C++ and C#, they are namespaces; for Ruby, they are modules. Partially because of the availability of packages, Java does not have friend functions or friend classes. In Ada, packages can be used as naming encapsulations.

Review Questions |
519 |
R E V I E W Q U E S T I O N S
1.What are the two kinds of abstractions in programming languages?
2.Define abstract data type.
3.What are the advantages of the two parts of the definition of abstract data type?
4.What are the language design requirements for a language that supports abstract data types?
5.What are the language design issues for abstract data types?
6.Explain how information hiding is provided in an Ada package.
7.To what is the private part of an Ada package specification visible?
8.What is the difference between private and limited private types in Ada?
9.What is in an Ada package specification? What about a body package?
10.What is the use of the Ada with clause?
11.What is the use of the Ada use clause?
12.What is the fundamental difference between a C++ class and an Ada package?
13.From where are C++ objects allocated?
14.In what different places can the definition of a C++ member function appear?
15.What is the purpose of a C++ constructor?
16.What are the legal return types of a constructor?
17.Where are all Java methods defined?
18.How are C++ class instances created?
19.How are the interface and implementation sections of an Objective-C class specified?
20.Are Objective-C classes types?
21.What is the access level of Objective-C methods?
22.What is the origin of the syntax of method calls in Objective-C?
23.When are constructors implicitly called in Objective-C?
24.Why are properties better than specifying an instance variable to be public?
25.From where are Java class instances allocated?
26.Why does Java not have destructors?
27.Where are all Java methods defined?
28.Where are Java classes allocated?
29.Why are destructors not as frequently needed in Java as they are in C++?

520Chapter 11 Abstract Data Types and Encapsulation Constructs
30.What is a friend function? What is a friend class?
31.What is one reason Java does not have friend functions or friend classes?
32.Describe the fundamental differences between C# structs and its classes.
33.How is a struct object in C# created?
34.Explain the three reasons accessors to private types are better than making the types public.
35.What are the differences between a C++ struct and a C# struct?
36.Why does Java not need a use clause, such as in Ada?
37.What is the name of all Ruby constructors?
38.What is the fundamental difference between the classes of Ruby and those of C++ and Java?
39.How are instances of Ada generic classes created?
40.How are instances of C++ template classes created?
41.Describe the two problems that appear in the construction of large programs that led to the development of encapsulation constructs.
42.What problems can occur using C to define abstract data types?
43.What is a C++ namespace, and what is its purpose?
44.What is a Java package, and what is its purpose?
45.Describe a .NET assembly.
48. What elements can appear in a Ruby module?
P R O B L E M S E T
1.Some software engineers believe that all imported entities should be qualified by the name of the exporting program unit. Do you agree? Support your answer.
2.Suppose someone designed a stack abstract data type in which the function top returned an access path (or pointer) rather than returning a copy of the top element. This is not a true data abstraction. Why? Give an example that illustrates the problem.
3.Write an analysis of the similarities of and differences between Java packages and C++ namespaces.
4.What are the disadvantages of designing an abstract data type to be a pointer?
5.Why must the structure of nonpointer abstract data types be given in Ada package specifications?
6.Discuss the advantages of C# properties, relative to writing accessor methods in C++ or Java.