Download presentation
Presentation is loading. Please wait.
1
Peter Müller, MIT John Mitchell, Stanford
Object-Oriented Programming & Design (Adapted from Object Oriented Programming – Timothy Budd) Lecture 1
2
Programming Paradigm A way of conceptualizing what it means to perform computation and how tasks to be carried out on the computer should be structured and organized Imperative : Machine-model based Functional : Equations; Expression Evaluation Logical : First-order Logic Deduction Object-Oriented : Programming with Data Types
3
What is OOP? Object-Oriented Programming (OOP) is a programming paradigm in which one models a problem in terms of the entities and concepts found in the problem domain
4
Why Use OOP? OOP is a tool that helps developers manage better the increasingly complex software projects they face today
5
Software Today The economies of ALL developed nations are dependent on software More and more systems are software controlled It has been said that modern aircrafts are simply computers with wings. E.g., the Boeing 777 has more than 4 million lines of code to control subsystems and aid pilots in flight management
6
Software Development It’s hard!
Important to distinguish “easy” systems (e.g., one developer, one user) from “hard” systems (e.g., multiple developers, multiple users, products) Experience with “easy” systems is misleading. One person techniques do not scale up The problem is complexity. Many sources, but size is key
7
Flexibility Leads to Complexity
Software offers the ultimate flexibility A developer can express almost any kind of abstraction While the construction industry has uniform building codes and standards, few such standards in the software industry
8
Our task: engineer the illusion of simplicity!
9
The “software crisis” We’ve been in the midst of a “software crisis” ever since the 1968 NATO meeting Difficulties of building big software loomed so large that in 1968 the NATO Science Committee convened some 50 top programmers, computer scientists and captains of industry to plot a course out of what had come to be known as the software crisis Refers to our inability to produce or maintain high-quality software at a reasonable price and on schedule. Basically, we suck
10
A Solution - Software Engineering
Greater emphasis on systematic development A concentration on finding out the user’s requirements Formal/Semi Formal specification of the requirements of a system Greater emphases on trying to ensure error free code
11
OOP for Complexity Control
Usually, we use “complexity” to mean “run-time complexity” or “space complexity” However, measures of complexity can take other forms, such as Development time and costs Maintenance time and costs Error time and costs OOP is a complexity control tool
12
Understanding the Problems
Considering the problems in software development and the goals that software development seeks to achieve. These are: Meeting the user’s needs Low cost of production High performance Portability Low cost of maintenance High reliability Delivery on time
13
Software Quality External Quality Factors Internal Quality Factors
User/Client perspective Correctness, Speed, Ease of use, etc Internal Quality Factors Designer / Implementer perspective Modularity, Readability, etc Internal Quality is a means to achieve External Quality
14
Expressive Power vs Naturalness
Object-oriented techniques do not provide any new computational power that permits problems to be solved that cannot, in theory, be solved by other means (Church-Turing Hypothesis) But object-oriented techniques do make it easier and more natural to address problems in a fashion that tends to favor the management of large software projects
15
Types of OOP Languages Languages, such as Smalltalk, are called pure object-oriented languages Everything in the language is an object All execution takes place by means of message passing Languages such as C++ are called hybrid object-oriented languages Combine OOP with traditional languages
16
What is “object-oriented”?
A system is said to be object-oriented if it exhibits 4 categories of traits Abstraction and classification Encapsulation and data hiding Inheritance and polymorphism Message passing
17
Object-Oriented Programming & Design Lecture 2
18
Chapter 1 Thinking Object-Oriented
19
Why has OOP Remained Popular for so long?
OOP has been the dominant programming paradigm for more than twenty years. Why is it so popular? Proven record of success Scales well from small problems to large Nevertheless, programming is still a task that requires skill and learning Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
20
Disclaimer Effective use of object-oriented principles requires one to view the world in a new way The use of an object oriented language does not make one an object oriented programmer “Fortran programs can be written in any language”
21
A New Paradigm Object-oriented programming is often described as a new paradigm. We start by considering the definition of this term: Paradigm n. A list of all the inflectional forms of a word taken as illustrative example of the conjugation or declension to which it belongs. An example or model. [Late Latein paradigma, from Greek paradeigma, modern paradeiknunai, to compare, exhibit.] Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
22
Sapir-Whorf Hypothesis
In linguistics there is a hypothesis that the language in which an idea or thought is expressed colors or directs in a very emphatic manner that nature of the thought Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
23
The SWH argues that we experience the world based on the words we have
In an experiment, people were asked to describe how many bands or stripes they saw in a rainbow Since rainbows are a continuum of colors, no empirical stripes or bands Nevertheless, people saw as many stripes or bands as their language possessed primary color words Inuit language and snow, Arabic language and camels Is it true that the way we think is completely determined by the language we use? This implies that: The words we have determine the things we can know If we have an experience, we are confined not just in our communication of it, but also in our knowledge of it, by the words we have
24
Arguments against this hypothesis?
People usually have trouble expressing themselves and are aware that the language is not adequate for what they mean “That’s not quite what I meant to say…” This provides evidence that what is being thought is not a set of words because one can understand a concept without being able to express it in words Truth probably somewhere in the middle, language may not complete determine but influences the way we think
25
Sapir-Whorf Hypothesis (cont’d)
What in the world does this have to do with computer programming languages? What is true of natural languages is even more true of artificial computer languages Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
26
Example from Computer Languages
A student working in DNA research had the task of finding whether any pattern of length M (M fixed and small) is repeated in a given DNA sequence of length N (N very very large) ACTCGGATCTTGCATTTCGGCAATTGGACCCTGACTTGGCCA ... Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
27
Example from Computer Languages
Wrote the simplest (and therefore, most efficient?) Fortran program: DO 10 I = 1, N-M DO 10 J = I+1, N-M FOUND = .TRUE. DO 20 K = 1, M 20 IF X[I+K-1] .NE. X[J+K-1] THEN FOUND = .FALSE. IF FOUND THEN ... 10 CONTINUE Took a depressingly long time. Asymptotic time complexity? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
28
A Better Solution A friend writing in APL found a much better solution by rearranging the data and sorting Reorganize in NxM matrix A C T C G G positions 1 to M C T C G G A positions 2 to M+1 T C G G A T positions 3 to M+2 C G G A T T positions 4 to M+3 G G A T T C positions 5 to M+4 G A T T C T positions 6 to M+5 . . . Sort matrix on rows and look for equal adjacent rows Ran surprisingly quickly, thesis saved Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
29
What lead to the discovery?
Why did the APL programmer find the better solution? Fortran programmer was blinded by a culture that valued loops, simple programs. Fortran programmer thinks in terms of loops Sorting is a built-in operation in APL, good programmers try to find novel uses for sorting. APL programmer thinks in terms of manipulating sequences; sort is built-in, loops do not exist APL is not a “more efficient” language than Fortran The fundamental point is that the language you speak leads you in one direction or another Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
30
Rule du Jour If the only tool you have is a hammer, everything in the world looks like a nail.
31
Church's Conjecture But what about the Sapir-Whorf hypothesis, that says there are some thoughts you can express in one language that you cannot express in another? In computation we have the following assertion: Church's Conjecture: Any computation for which there exists an effective procedure can be realized by a Turing machine language Anything can be done in any language, but it may simply be easier or more efficient to use one language or another. Note that is almost directly opposite to the SWH Would YOU want to write an event-driven GUI interface in Turing machine language? Bottom line: Languages lead you, but do not prevent you from going anywhere you want Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
32
Imperative Programming
So, what are the paradigms of programming? Imperative programming is the “traditional” model of computation State Variables Assignment Loops A processing unit is separate from memory, and “acts” upon memory Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
33
Visualization of Imperative Programming
Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
34
Why Not Build a Program out of Computers?
Alan Kay thought about this conventional design of the computer, and asked why we constructed the whole out of pieces that were useless by themselves Why not build a whole out of pieces that were similar at all levels of detail? (Think of fractals) Idea: A program can be build out of little computing agents Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
35
Recursive Design The structure of the part mirrors the structure of the larger unit Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
36
Kay's Description of Object-Oriented Programming
Object-oriented programming is based on the principle of recursive design Everything is an object Objects perform computation by making requests of each other through the passing of messages Every object has it's own memory, which consists of other objects Every object is an instance of a class. A class groups similar objects The class is the repository for behavior associated with an object Classes are organized into singly-rooted tree structure, called an inheritance hierarchy We can illustrate these principles by considering how I go about solving a problem in real life Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
37
Illustration of OOP Concepts -- Sending Flowers to a Friend
To illustrate the concepts of OOP in an easily understood framework, consider the problem of sending flowers to a friend who lives in a different city. Chris is sending flowers to Robin. Chris can't deliver them directly. So Chris uses the services of the local Florist Chris tells the Florist (named Fred) the address for Robin, how much to spend, and the type of flowers to send Fred contacts a florist in Robins city, who arranges the flowers, then contacts a driver, who delivers the flowers If we start to think about it, there may even be other people involved in this transaction. There is the flower grower, perhaps somebody in charge of arrangements, and so on Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
38
Agents and Communities
Our first observation is that results are achieved through the interaction of agents, which we will call objects Furthermore, any nontrivial activity requires the interaction of an entire community of objects working together Each object has a part to play, a service they provide to the other members of the community Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
39
Elements of OOP - Objects
So we have Kay's first principle Everything is an object Actions in OOP are performed by agents, called instances or objects There are many agents working together in my scenario. We have Chris, Robin, the florist, the florist in Robins city, the driver, the flower arranger, and the grower. Each agent has a part to play, and the result is produced when all work together in the solution of a problem Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
40
Elements of OOP - Messages
And principle number 2: Objects perform computation by making requests of each other through the passing of messages Actions in OOP are produced in response to requests for actions, called messages. An instance may accept a message, and in return will perform an action and return a value To begin the process of sending the flowers, Chris gives a message to Fred. Fred in turn gives a message to the florist in Robins city, who gives another message to the driver, and so on Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
41
Information Hiding Notice that I, as a user of a service being provided by an object, need only know the name of the messages that the object will accept I need not have any idea how the actions performed in response to my request will be carried out Having accepted a message, an object is responsible for carrying it out Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
42
Elements of OOP - Receivers
Messages differ from traditional function calls in two very important respects: In a message there is a designated receiver that accepts the message The interpretation of the message may be different, depending upon the receiver Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
43
Object-Oriented Programming & Design Lecture 3
44
OOP: The General Principle
“ An object oriented program is structured as a community of interacting agents called objects. Action is initiated in object oriented programming by the transmission of a message to an agent (an object). The message encodes the request for action and is accompanied by additional information (arguments) needed to carry out the request. The receiver is the agent to which the message is sent. If the receiver accepts the message it accepts the responsibility to carry out the indicated action. In response to a message the receiver will perform some method to satisfy the request. “
45
OOP: A Way of Viewing the World
“ Chris wants to send some flowers to his friend Robin who lives in a distant city. Because of the distance, Chris cannot pick up the flowers and bring them to Robin in person. Chris goes down to Fred a local florist and tells him the number and type of flowers he wants together with the address they need to be delivered to. Chris can rest assure that the flowers will be delivered. ”
46
Agents, Responsibility, Messages, Methods
Chris finds an appropriate agent (Fred) And passes to her a message containing a request It is the responsibility of Fred to satisfy the request There is some method -a set of operations- used by Fred to do this Chris does not need to know the particular method he will use, this information is hidden from inspection
47
Behavior and Interpretation
Although different objects may accept the same message, the actions (behavior) the object will perform will likely be different When Fred would ask his wife Beth to send some flowers to Robin for her birthday she might use a different method than the florist Fred determination of what behavior to perform may be made at run-time, a form of late binding The fact that the same name can mean two entirely different operations is one form of polymorphism, a topic we will discuss at length in subsequent chapters Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
48
Elements of OOP - Recursive Design
Every object has it's own memory, which consists of other objects Each object is like a miniature computer itself - a specialized processor performing a specific task Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
49
Non-interference It is important that objects be allowed to perform their task however they see fit, without unnecessary interactions or interference with other objects “Instead of a bit-grinding processor ... plundering data structures, we have a universe of well-behaved objects that courteously ask each other to carry out their various desires” -- Dan Ingalls “Ask not what you can do to your data structures, but ask what your data structures can do for you” Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
50
Elements of OOP - Classes
Every object is an instance of a class. A class groups similar objects The class is the repository for behavior associated with an object The behavior I expect from Fred is determined from a general idea I have of the behavior of Florists We say Fred is an instance of the class Florist Behavior is associated with classes, not with individual instances. All objects that are instances of a class use the same method in response to similar messages Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
51
Hierarchies of Categories
But there is more that I know about Fred than just that he is a Florist. I know he is a ShopKeeper, and a Human, and a Mammal, and a Material Objects, and so on At each level of abstraction I have certain information recorded. That information is applicable to all lower (more specialized) levels Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
52
Elements of OOP - Inheritance
The principle that knowledge of a more general category is also applicable to a more specific category is called inheritance Classes can be organised into a hierarchical inheritance structure. A child class (or subclass) will inherit attributes from a parent class (super class) higher up in the hierarchy. An abstract parent class is a class for which there are no direct instances, it is only introduced to group subclasses
53
Hierarchies of Categories
Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
54
Class Hierarchies Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
55
Elements of OOP - Overriding
Subclasses can alter or override information inherited from parent classes: All mammals give birth to live young A platypus is an egg-laying mammal The search for a method to use in response to a message starts with the receiver’s class and continues up the parent chain. When methods with the same name are available higher in the class hierarchy the method that executes is said to override the inherited behavior Inheritance combined with overriding are where most of the power of OO originates Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
56
Problem Solving Because the OOP view is similar to the way in which people go about solving problems in real life (finding another agent to do the real work!), intuition, ideas, and understanding from everyday experience can be brought to bear on computing On the other hand, common sense was seldom useful when computers were viewed in the process-state model, since few people solve their everyday problems using pigeon-holes Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
57
From Newsweek “Unlike the usual programming method -- writing software one line at a time-- NeXT's “object-oriented” system offers larger building blocks that developers can quickly assemble the way a kid builds faces on Mr. Potato Head.” Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
58
Chapter 2 Abstraction
59
Coping with Complexity
Is the complexity of a programming project linear in terms of the number of programmers involved? E.g., Can two programmers do in one month what one programmer can do in 2 months ? Interconnectedness, the dependence of one portion of code on another portion, is responsible for this phenomena Abstraction mechanisms try to cope with this and object oriented techniques offer yet another step forward
60
Abstraction What is abstraction?
Abstraction is the purposeful suppression, or hiding, of some details of a process or artifact, in order to bring out more clearly other aspects, details, or structure Think of a model, give an example of a model Do we need it? Why? Yes, mainly because it helps us to deal with complexity Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
61
Information Hiding Information hiding is the purposeful omission of details in the development of an abstract representation Information hiding is what allows abstraction to control complexity Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
62
Abstraction in an Atlas
Think of an atlas, and the various different levels of maps A map of the world, contains mountain ranges, large political boundaries A map of a continent, contains all political boundaries, large cities A map of a country, contains more cities, major roads A map of a large city, roads, major structures A map of a portion of a city, buildings, occupants Each level contains information appropriate to the level of abstraction Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
63
Levels of Abstraction in OO Programs
At the highest level of abstraction we view a program as a community of interacting objects Important characteristics here are the lines of communication between the various agents Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
64
Levels of Abstraction in OO Programs (cont’d)
The next level of abstraction is found in some (but not all) OO languages. A package, Unit or Name Space allows a programmer to surround a collection of objects (a small community in itself) with a layer, and control visibility from outside the module Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
65
Levels of Abstraction in OO Programs (cont’d)
The next level of abstraction considers the relationship between two individual objects. Typically one is providing a service, and the other is using the service Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
66
Levels of Abstraction in OO Programs (cont’d)
We can next examine just the person providing a service, independent of the client. We define the nature of the services that are offered, but not how those services are realized Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
67
Levels of Abstraction in OO Programs (cont’d)
Next we look at the services provided, but from the implementation side public class LinkedList implements Stack ... { public void pop () throws EmptyStackException { ... } ... } Concern here is with the high level approach to providing the designated service Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
68
Levels of Abstraction in OO Programs (cont’d)
Finally, we consider the implementation of each method in isolation public class LinkedList implements Stack ... { ... public void pop () throws EmptyStackException { if (isEmpty()) throw new EmptyStackException(); removeFirst(); // delete first element of list } Every level is important, and often you move quickly back and forth between levels Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
69
Object-Oriented Programming & Design Lecture 4
70
Finding the Right Level of Abstraction
A critical problem in early stages of development is to determine what details are appropriate at each level of abstraction, and (often more importantly) what details should be omitted One does not want to ignore or throw away important information But one does not want to manage too much information, or have the amount of information hide critical details Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
71
Finding the Right Level of Abstraction (cont’d)
A chess board problem Can a chess board, which has 64 squares, be tiled by 32 dominoes, each covering exactly two squares? YES In order to solve this problem, what details do we need to keep, and what details we can ignore? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
72
Finding the Right Level of Abstraction (cont’d)
The mutilated chess board problem If two diagonally opposite squares are removed, can the remaining 62 squares be tiled by dominoes? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
73
Forms of Abstraction Abstraction is used to help understand a complex system In a certain sense, abstraction is the imposition of structure on a system What are the techniques that we use for handling complexity? E.g., what is a computer? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
74
Is-a and Has-a Abstraction
Two of the most important types of abstraction are the following: Division into parts -- Has-a abstraction Division into specialization -- Is-a abstraction Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
75
Has-a Abstraction Most common technique people use to help understand complex systems Division into parts takes a complex system, and divides into into component parts, which can then be considered in isolation Characterized by sentences that have the words “has-a” A car has-a engine, and has-a transmission A bicycle has-a wheel A window has-a menu bar Allows us to drop down a level of complexity when we consider the component in isolation Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
76
Is-a Abstraction Is-a abstraction takes a complex system, and views it as an instance of a more general abstraction Characterized by sentences that have the words “is-a” A car is a wheeled vehicle, which is-a means of transportation A bicycle is-a wheeled vehicle A pack horse is-a means of transportation Allows us to categorize artifacts and information and make it applicable to many different situations Mammals are animals that have hair and nurse their young A cat is a mammal, a dog is a mammal, … Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
77
Other Types of Abstraction -- Composition
While is-a and has-a are two important types of abstraction, there are others Composition is one example; a form of has-a; characterized by the following Primitive forms Rules for combining old values to create new values The idea that new values can also be subject to further combination Examples include regular expressions, type systems, windows, lots of other complex systems Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
78
Patterns When faced with a new problem, most people will consider successful solutions to previous problems with similar characteristics Patterns are another attempt to document and reuse abstractions Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
79
A Short History of Abstraction Mechanisms
Another way to better understand OOP is to put it in context with the history of abstraction in computer science Assembly languages Procedures Modules ADT The Service View Objects The future.... Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
80
Assembly Languages Assembly languages and linkers were perhaps the first tools used to abstract features of the bare machine Addresses could be represented symbolically, not as a number Symbolic names for operations Linking of names and locations performed automatically Abstraction allowed the programmer to concentrate more effort on defining the task to be performed and less on the steps necessary to complete the task Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
81
Procedures and Functions
Libraries of procedures and functions (such as mathematical or input/output libraries) provided the first hints of information hiding They permit the programmer to think about operations in high level terms, concentrating on what is being done, not how it is being performed But they are not an entirely effective mechanism of information hiding Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
82
Procedures and Functions
int datastack[100]; int datatop = 0; void init() // initialize the stack { datatop = 0; } void push(int val) // push a value on to the stack { if (datatop < 100) datastack [datatop++] = val; } int pop() // pop element from the stack { if (datatop > 0) return datastack [--datatop]; return 0; } Where can you hide the implementation? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
83
Procedures and Functions
In the "good ol' days" of programming, data and functions coexisted on a casual basis During the 1960s and 1970s, structured programming helped bring organization to this picture by emphasizing the use of Abstract Data Types (ADTs):
84
Modules The solution to the problem of global name space congestion what the introduction of the idea of a module A module provides the ability to divide a name space into 2 parts The public part is accessible outside the module The private part is only accessible within the module Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
85
Parnas's Principles David Parnas described two principles for the proper use of modules: One must provide the intended user of a module with all the information needed to use the module correctly, and with nothing more One must provide the implementor of a module with all the information needed to complete the module, and nothing more Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
86
Modules Solves the problem of encapsulation -- but what if your programming task requires two or more stacks? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
87
Abstract Data Type A type is a collection of values
E.g., Boolean, Integer A data type is a type together with a collection of operations to manipulate the type E.g., Integer data type An abstract data type (ADT) is the realization of a data type as a software component. It does not specify how the data type is implemented
88
Abstract Data Types An Abstract Data Type is a programmer-defined data type that can be manipulated in a manner similar to system-provided data types Must have the ability to instantiate many different copies of the data type Data type can be manipulated using provided operations, without knowledge of internal representation But ADTs were important not because they were data structures, but because they provided an easily characterized service to the rest of an application Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
89
What Does the Future Hold
What will be the next evolutionary step in software? Prediction is hard, particularly about the future However, one you have accepted the idea of an application formed from interacting agents, there is no reason why those components must exist on the same computer (distributed computing) or be written in the same language (components) So some of the trends we see today in software are natural results of the OOP mind set Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
90
Object-Oriented Programming & Design Lecture 5
91
Structs A struct holds data, like an array
Each unit of data in a struct is called a data member (or member) they are called “elements” in arrays In a struct, each data member can have a different data type in arrays, the data type of each element is the same
92
Example Using a Struct 1 #include <iostream>
2 #include <iomanip> 3 #include <string> 4 5 using namespace std; 6 7 struct CarType { 8 string maker; 9 int year; 10 float price; 11 }; 12 13 void getYourCar( CarType & car ); 14 Don’t forget this semicolon.
93
Example Using a Struct (cont.)
15 int main( ) 16 { CarType myCar, yourCar; 18 myCar.maker = "Mercedes"; // I wish myCar.year = 2005; myCar.price = ; 22
94
Example Using a Struct (cont.)
getYourCar( yourCar ); 24 cout << "Your car is a: " << yourCar.maker << endl; cout << fixed << showpoint << setprecision( 2 ) << "I'll offer $" << yourCar.price << " for your car." << endl; 29 return 0; 31 } 32
95
Example Using a Struct (cont.)
33 void getYourCar( CarType & car ) 34 { 35 cout << "Enter your maker: "; 36 cin >> car.maker; 37 cout << "Enter the year: "; 38 cin >> car.year; 39 cout << "Enter the price: $"; 40 cin >> car.price; 41 }
96
Object Assignment An object of a struct can be assigned to another object of the same struct type: myCar = yourCar; This assigns each data member in yourCar to the corresponding data member of myCar Also assigns any array data members
97
Classes A class is similar to a struct
A class contains data members, but it also contains function members Objects are made from classes, similarly to the way that objects are made from structs The main program communicates with the objects data is passed from main program to object and from object back to the main program
98
Main Program Using Objects
Object A Main Program Object C Object B
99
Main Program Using Objects
Object A Main Program Object C Object B
100
Main Program Using Objects
Object A Main Program Object C Object B
101
Main Program Using Objects
Object A Main Program Object C Object B
102
Main Program Using Objects
Object A Main Program Object C Object B
103
Main Program Using Objects
Object A Main Program Object C Object B
104
Main Program Using Objects
Object A Main Program Object C Object B
105
Main Program Using Objects
Object A Main Program Object C Object B
106
Main Program Using Objects
Object A Main Program Object C Object B
107
How the Main Program Uses A Class Object
The main program does not access the data within a class object The main program only accesses the functions of a class object communication occurs by passing data as parameters into the object’s function the object passes data to the main program through its return type
108
Main Program and Object
public: functions private: data Main Program
109
Main Program Calls a Function in the Object
public: functions private: data Main Program
110
The Function Accesses Data
Object public: functions private: data Main Program
111
Function Returns a Value Back to the Main Program
Object public: functions private: data Main Program
112
Main Program Calls a Different Function
Object public: functions private: data Main Program
113
Function Calls Another Function
Object public: functions private: data Main Program
114
Second Function Accesses Data
Object public: functions private: data Main Program
115
Second Function Returns Back to First Function
Object public: functions private: data Main Program
116
First Function Accesses Data
Object public: functions private: data Main Program
117
Function Returns Back to Main Program
Object public: functions private: data Main Program
118
Example of a Class 1 class Checkbook 2 { 3 public:
2 { 3 public: void setBalance( float amount ); bool writeCheck( float amount ); void deposit( float amount ); float getBalance( ); float getLastCheck( ); float getLastDeposit( ); 10 private: float balance; 12 float lastCheck; float lastDeposit; 14 }; This class definition is placed into its own file, called the class specification file, named checkbook.h (by convention)
119
Example of a Class (cont.)
1 class Checkbook 2 { 3 public: void setBalance( float amount ); bool writeCheck( float amount ); void deposit( float amount ); float getBalance( ); float getLastCheck( ); float getLastDeposit( ); 10 private: float balance; 12 float lastCheck; float lastDeposit; 14 }; The writeCheck function returns false if the amount of the check is greater than the balance; returns true otherwise.
120
Example of a Class (cont.)
1 class Checkbook 2 { 3 public: void setBalance( float amount ); bool writeCheck( float amount ); void deposit( float amount ); float getBalance( ); float getLastCheck( ); float getLastDeposit( ); 10 private: float balance; 12 float lastCheck; float lastDeposit; 14 }; Don’t forget the semicolon.
121
Example of a Class (cont.)
15 #include “checkbook.h” 16 17 void Checkbook::setBalance( float amount ) 18 { 19 balance = amount; 20 } The function definitions are placed into a separate file called the class implementation file. This file would be called checkbook.cpp (by convention).
122
Example of a Class (cont.)
15 #include “checkbook.h” 16 17 void Checkbook::setBalance( float amount ) 18 { 19 balance = amount; 20 } The balance variable is declared in the private section of the class definition.
123
Example of a Class (cont.)
15 #include “checkbook.h” 16 17 void Checkbook::setBalance( float amount ) 18 { 19 balance = amount; 20 } Special notation for class function definitions
124
Example of a Class (cont.)
21 bool Checkbook::writeCheck( float amount ) 22 { 23 if ( amount > balance ) 24 return false; 25 balance -= amount; 26 lastCheck = amount; 27 return true; 28 }
125
Example of a Class (cont.)
29 void Checkbook::deposit( float amount ) 30 { 31 balance += amount; 32 lastDeposit = amount; 33 }
126
Example of a Class (cont.)
34 float Checkbook::getBalance( ) 35 { 36 return balance; 37 } 38 39 float Checkbook::getLastCheck( ) 40 { 41 return lastCheck; 42 } end of checkbook.cpp
127
A Program that Uses the Checkbook Class
1 #include <iostream> 2 #include <iomanip> 3 #include "checkbook.h" 4 5 using namespace std; 6 7 int menu( ); 8 9 const int CHECK = 1, DEPOSIT = 2, BALANCE = 3, QUIT = 4; 10 11 int main( ) 12 { 13 Checkbook cb; 14 float balance, amount; 15 int choice; A main program that uses the Checkbook class is placed into a separate .cpp file
128
A Program that Uses the Checkbook Class (cont.)
16 cout << "Enter the initial balance: $"; 17 cin >> balance; 18 cb.setBalance( balance ); 19 20 cout << fixed << showpoint << setprecision( 2 );
129
A Program that Uses the Checkbook Class (cont.)
21 choice = menu( ); 22 while ( choice != QUIT ) { 23 if ( choice == CHECK ) { cout << "Enter check amount: $"; cin >> amount; if ( cb.writeCheck( amount ) ) 27 cout << "Check accepted." << endl; else { 29 cout << "Your balance is not high "; 30 cout << "enough for that check." << endl; 31 } } body of the while loop continues
130
A Program that Uses the Checkbook Class (cont.)
33 else if ( choice == DEPOSIT ) { 34 cout << "Enter deposit amount: $"; 35 cin >> amount; 36 cb.deposit( amount ); 37 cout << "Deposit accepted." << endl; 38 } body of the while loop continues
131
A Program that Uses the Checkbook Class (cont.)
else { // must be a balance request amount = cb.getBalance( ); cout << "Your balance is: $" << amount << endl; } 43 choice = menu( ); 45 } 46 47 return 0; 48 } 49 end of while loop
132
A Program that Uses the Checkbook Class (cont.)
50 int menu( ) 51 { 52 int choice; 53 54 cout << endl; 55 cout << "1 Write a check" << endl; 56 cout << "2 Make a deposit" << endl; 57 cout << "3 Get the balance" << endl; 58 cout << "4 Quit" << endl << endl; 59 cout << "Enter a number between 1 and 4: "; 60 cin >> choice; 61 return choice; 62 }
133
Keep In Mind The data members of a class cannot be accessed by a main program The object always retains the current values of its data members, even when object code is no longer executing Each function of a class can use the data members of the class as though they have been declared within the function
134
If Data Members were Accessed Directly…
Class Main Program int a; int b; int c; . Suppose the variables of a class were accessed by 100 places in a program
135
If Data Members were Accessed Directly… (cont.)
Class Main Program int arr[10] . Then we need to change the way the data is repre-sented (for maintenance)
136
If Data Members were Accessed Directly… (cont.)
Class Main Program int arr[10] . We need to change 100 lines of code in the main program!
137
Data Members Should Be Private
Class Main Program int foo( int x ) private: int a; int b; int c; . Here, the main program calls foo from 100 places.
138
Data Members Should Be Private (cont.)
Class Main Program int foo( int x ) private: int a; int b; int c; . Then foo accesses the private data members.
139
Data Members Should Be Private (cont.)
Class Main Program int foo( int x ) private: int arr[10] . If the data needs to change, the body of foo will need to be rewritten.
140
Data Members Should Be Private (cont.)
Class Main Program int foo( int x ) private: int arr[10] . However, the function call of foo and return type will stay the same.
141
Data Members Should Be Private (cont.)
Class Main Program int foo( int x ) private: int arr[10] . No changes need to be made in the main program!
142
Data Members Should Be Private (cont.)
Class Main Program int foo( int x ) private: int arr[10] . Program maintenance is easier this way…
143
Data Members Should Be Private (cont.)
Class Main Program int foo( int x ) private: int arr[10] . especially if there is more than one program using the class.
144
Struct vs. Class Functions can be placed in a struct, but only when necessary The public and private keywords can be left out of a class (rare) The public and private keywords can be placed into a struct (rare) So what is the difference between a struct and a class?
145
Struct vs. Class (cont.) If public and private are not used in a struct, all data members are public by default If public and private are not used in a class, all data members are private by default
146
Conventions By convention, we use structs when we want all data members to be public structs are typically defined and used within the client’s program, not in a separate file typically used for records of information By convention, we use classes when we want all data members to be private (for maintenance purposes)
147
Object-Oriented Programming & Design Lecture 6
148
Chapter 3 Object-Oriented Design
149
Why Start with Design Why start our discussion with a chapter on design? Object-oriented thinking begins with object-oriented design It is the easiest way to develop an appreciation of the problems of programming in the large (realistic modern software development) Without understanding programming in the large, one cannot understand the importance of OOP Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
150
Programming in the Small and Programming in the Large
One programmer, understands everything from top to bottom Major problem is the development of algorithms Programming in the Large: System is developed by large team of programmers Major problems are management of details and communication between programmers and between their respective software subsystems Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
151
Basis for Design Consider for the moment what aspects of a problem are known first: Data Structures Functions A Formal Specification Behavior A design technique based on behavior can be applied from the very beginning of a problem, whereas techniques based on more structural properties necessarily require more preliminary analysis Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
152
Responsibility Driven Design
A design technique that has the following properties: Can deal with ambiguous and incomplete specifications Naturally flows from Analysis to Solution Easily integrates with various aspects of software development Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
153
Object-Oriented Analysis
Before you can build an object-oriented system, you have to define the classes (objects) that represent the problem to be solved, how the classes relate and interact, the inner workings of objects (attributes and operations), and communication mechanisms (messages) that allow them to work together Object-Oriented Analysis begins with a description of use-cases. Class-responsibility-collaborator (CRC) modeling transforms the information contained in use-cases into a representation of classes and their collaborations with other classes. The characteristics of classes are then modeled using UML
154
Scenarios People find it easier to relate to real-life examples than to abstract descriptions Scenarios are real-life examples of how a system can be used They should include A description of the starting situation A description of the normal flow of events A description of what can go wrong Information about other concurrent activities A description of the state when the scenario finishes
155
Use cases Use-cases are a scenario based technique in the UML which identify the actors in an interaction and which describe the interaction itself You apply use cases to capture the intended behaviour of the system you are developing, without having to specify how that behaviour is implemented A set of use cases should describe all possible interactions with the system
156
Use cases A use case is a typical sequence of actions that a user performs in order to complete a given task The objective of use case analysis is to model the system From the point of view of how users interact with this system When trying to achieve their objectives A use case model consists of A set of use cases An optional description or diagram indicating how they are related
157
Use cases The first step in use case analysis is to determine the types of users or other systems that will use the facilities of the system. These are called actors An actor is a role that a user or some other system plays when interacting with the system The next step is to determine the tasks that each actor will need to do with the system. Each task is called a use case because it represents a particular way of using the system
158
Use cases In general, a use case should cover the full sequence of steps from the beginning of a task until the end A use case should describe the user’s interaction with the system, not the computations the system performs A use case should be written so as to be as independent as possible from any particular user interface design A use case should only include actions in which the actor interacts with the system
159
Building a use case model
To build a complete use case model we need to describe the use cases in more detail A use case model consists of a set of use cases, and optional descriptions or diagrams indicating how they are related
160
How to describe a single use case
A. Name: Give a short, descriptive name to the use case B. Actors: List the actors who can perform this use case C. Goals: Explain what the actor or actors are trying to achieve D. Preconditions: State of the system before the use case E. Description: Give a short informal description F. Related use cases: List use cases that are generalizations, extensions, or inclusions G. Steps: Describe each step showing actions and responses H. Postconditions: State of the system in following completion
161
How to describe a single use case
Example: Briefly describe a use case for leaving an automated car parking, paying cash
162
Use case diagrams A use case diagram is UML’s notation for showing the relationships among a set of use cases and actors A use case diagram can help the software engineer to convey a high-level picture of the functionality of the system
163
Library system use case diagram
Example: Use-case diagram for a course registration system
164
Extensions Used to make optional interactions explicit or to handle exceptional cases By creating separate use case extensions, the description of the basic use case remains simple A use case extension must list all the steps from the beginning of the use case to the end Including the handling of the unusual situation
165
Generalizations Much like superclasses in a class diagram
A generalized use case represents several similar use cases One or more specializations provides details of the similar use cases
166
Inclusions Allow one to express commonality between several different use cases Are included in other use cases Even very different use cases can share sequence of actions Enable you to avoid repeating details in multiple use cases
167
Example of generalization, extension and inclusion
Example: Use-case diagram for a home security system
168
Object-Oriented Programming & Design Lecture 7
169
Example of generalization, extension and inclusion
Example: Use-case diagram for a home security system
170
An Example, the IIKH Imagine you are the chief software architect in a major computing firm One day your boss rushes into your office with a specification for the next PC-based product. It is drawn on the back of a used dinner napkin, in handwriting that appears to be your boss’s Briefly, the Intelligent Interactive Kitchen Helper will replace the box of index cards of recipes in the average kitchen Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
171
Your Job Your job is to develop the software that will implement the IIKH Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
172
Abilities of the IIKH Here are some of the things a user can do with the IIKH [identified as a result of a use-case analysis]: Browse a database of recipes Add a new recipe to the database Edit or annotate an existing recipe Plan a meal consisting of several courses Scale a recipe for some number of users Plan a longer period, say a week Generate a grocery list that includes all the items in all the menus for a period Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
173
Scenarios A scenario is an instance of a use case
It expresses a specific occurrence of the use case A specific actor ... At a specific time ... With specific data Can be part of the Description field of a use case Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
174
An Example Scenario Alice Smith sits down at her computer and starts the IIKH. When the program begins, it displays a graphical image of a recipe box and identifies itself as the IIKH, product of IIKH incorporated. Alice presses the return button to begin. Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
175
An Example Scenario (cont’d)
In response to the key press, Alice is given a choice of a number of options. She elects to browse the recipe index, looking for a recipe for salmon that she wishes to prepare for dinner the next day. She enters the keyword “salmon” and is shown in response a list of various recipes. She remembers seeing an interesting recipe that used dill weed as seasoning. She refines the search, entering the words “salmon” and “dill weed”. This narrows the search to two recipes. Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
176
An Example Scenario (cont’d)
She selects the first. This brings up a new window in which an attractive picture of the finished dish is displayed, along with the list of ingredients, preparation steps, and expected preparation time. After examining the recipe, Alice determines it is not the recipe she wanted. She returns to the search result page and selects the second alternative. Examining this dish, Alice decides this is the one she had in mind. She requests a printout of the recipe, and the output is spooled to her printer. Alice selects “quit” from a program menu, and the application quits. Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
177
Software Components A software component is simply an abstract design entity with which we can associate responsibilities for different tasks May eventually be turned into a class, a function, a module, or something else A component must have a small well defined set of responsibilities A component should interact with other components to the minimal extent possible Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
178
CRC Cards Components are most easily described using CRC cards. A CRC card records the name, responsibilities, and collaborators of a component Inexpensive, Erasable, Physical Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
179
CRC Cards (cont’d) Responsibilities Collaborators
Express responsibilities as short verb phrases containing active rather than passive verbs Define what should be done, not how to do it (declarative) Include only essential information, not a great deal of detail Collaborators A collaborator for a class or object is another class or object with which the first class communicates to carry out its responsibilities The sender of a message usually is not one of the collaborators of the receiver
180
CRC Cards (cont’d) Identify an initial set of classes and objects. Can be done by performing a “grammatical parse” on scenarios or use case descriptions. Create one card for each Identify an initial set of responsibilities and collaborators for each card. This may lead to the identification of other classes and objects Spread the cards out on a desk or attach them to a wall For a group project, assign one or more cards to each person in the group Run through usage scenarios; as the flow of control passes to an object or class, bring that card to a prominent spot As the scenarios are played out, gaps in the design are filled in. This is a form of iterative refinement
181
A Component, The Greeter
Let us return to the development of the IIKH. The first component your team defines is the Greeter. When the application is started, the Greeter puts an informative and friendly welcome window (the greeting) on the screen Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
182
A Component, The Greeter (cont’d)
Offer the user the choice of several different actions Casually browse the database of recipes Add a new recipe Edit or annotate a recipe Review a plan for several meals Create a plan of meals Many of the details concerning exactly how this is to be done can be ignored for the moment Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
183
A Component, The Greeter (cont’d)
CRC card? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
184
The Recipe Database Component
Ignoring the planning of meals for the moment, your team elects to next explore the recipe database component Must Maintain the Database of recipes Must Allow the user to browse the database Must permit the user to edit or annotate an existing recipe Must permit the user to add a new recipe Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
185
The Who/What Cycle As we walk through scenarios, we go through cycles of identifying a what, followed by a who What action needs to be performed at this moment, Who is the component charged with performing the action Every what must have a who, otherwise it simply will not happen. Sometimes the who might not be obvious at first, i.e., who should be in charge of editing a recipe? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
186
Postponing Decisions Many decisions, such as the method of browsing, can be ignored for the moment, as they are entirely encapsulated within the recipe database component, and do not effect other components Scroll bars and windows? A virtual “book” with thumb-holes and flipping pages? Keywords and phrases? Only need to note that somehow the user can manipulate the database to select a specific recipe Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
187
Responsibilities of a Recipe
We make the recipe itself into an active data structure. It maintains information, but also performs tasks Maintains the list of ingredients and transformation algorithm Must know how to edit these data values Must know how to interactively display itself on the output device Must know how to print itself We will add other actions later (ability to scale itself, produce integrate ingredients into a grocery list, and so on) Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
188
The Planner Component Returning to the greeter, we start a different scenario. This leads to the description of the Planner Permits the user to select a sequence of dates for planning Permits the user to edit an existing plan Associates with Date object Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
189
The Date Component The Date component holds a sequence of meals for an individual date User can edit specific meals User can annotate information about dates (“Bob's Birthday”, “Christmas Dinner”, and so on) Can print out grocery list for entire set of meals Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
190
The Meal Component The Meal component holds information about a single meal Allows user to interact with the recipe database to select individual recipes for meals User sets number of people to be present at meal, recipes are automatically scaled Can produce grocery list for entire meal, by combining grocery lists from individual scaled recipes Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
191
The Six Components Having walked through the various scenarios, you team eventually decides everything can be accomplished using only six software components You can at this point assign the different components to different programmers for development Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
192
Interaction Diagrams The picture on the previous slide captures static relationships, but not the dynamic flow of messages in a scenario. That information can be recorded by an interaction diagram Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
193
Object-Oriented Programming & Design Lecture 8
194
Constructors A constructor is a method that is executed automatically whenever an instance is created If a C++ method is a constructor It has the same name as the class to which it belongs It has no return type specified A class can have more than one constructor (this is an example of function overloading) Handout #1
195
Constructor Execution
When is a constructor executed? When an instance is declared student s1(“John”, 19); When an instance is created using new student* sPtr; sPtr = new student(“John”, 19); When an argument is passed using call-by-value void process(student s); When a temporary instance is created s1 = student(“Martin”, 20);
196
Four Categories of Constructors
Default constructors system generated and user-defined Copy constructors Conversion constructors All other constructors
197
Default Constructors A default constructor is one that has no parameters The system automatically generates a default constructor for a class if and only if the programmer does not define any constructor(s) for the class. It is called a system-generated default constructor A system-generated default constructor does nothing (i.e., the constructor body is empty) A default constructor is called when an instance is created, but no arguments are specified student s1; student s1(); // NO! What is this doing?
198
Default Constructors Builtin types, such as int, can be viewed as classes that have default constructors When an array of class instances is declared, the default constructor for the class is called for each instance, in the order of their index numbers
199
Constructors and Data Members
If a class has data members, the constructors of those data members are executed prior to the constructor of the class containing the data members Unless otherwise specified, the default constructors of the data members are called when an instance of the class containing the data members is created class studentRecord { private: student s; char* address //… public: studentRecord(const char* n, int a, const char* a); };
200
Constructors and Data Members
But one can specify different constructors to be called for the data members studentRecord(const char* n, int a, const char* a):student(n, a) { … } This technique can also be used to initialize data members that belong to a builtin type
201
Copy Constructors A copy constructor is one that has exactly one parameter, where the parameter is an instance of the same class The system automatically generates a copy constructor for a class if and only if the programmer does not define a copy constructor for the class. It is called a system-generated copy constructor A system-generated copy constructor does a memberwise copy of the parametric instance to the new instance One should always write a copy constructor if the members of a class point to dynamically allocated space. WHY?
202
Conversion Constructors
A conversion constructor is a constructor that has exactly one parameter, where the parameter is not an instance of the same class Conversion constructors are not generated automatically by the compiler
203
Destructors A destructor is a method that executed when an instance is destroyed Destructors are generally used to “clean up” before an instance is deallocated If a C++ method is a destructor Its name if the name of its class, preceded by a tilde (~) It has no return type specified It has a void parameter list The system automatically generates a destructor for a class if and only if the programmer does not define one. It is called a system-generated destructor The system-generated destructor does nothing (i.e., the method body is empty) The destructors of an object’s data members are executed after the destructor of the class containing the data members
204
A Day in the Life of an Object
Creation (allocation) Component constructors are called Constructor is called Instance is manipulated Destructor is called Component destructors are called Destruction (deallocation)
205
Object-Oriented Programming & Design Lecture 9
206
Characteristics of Components
Let us return to the idea of a software component There are many different aspects to this simple idea, we will consider just a few: Behavior and State Instances and Classes Coupling and Cohesion Interface and Implementation Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
207
Behavior and State All components can be characterized by two aspects:
The behavior of a component is the set of actions a component can perform. The complete set of behavior for a component is sometimes called the protocol The state of a component represents all the information (data values) held within a component Notice that it is common for behavior to change state. For example, the edit behavior of a recipe may change the preparation instructions, which is part of the state Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
208
Instances and Classes We can now clarify a point we earlier ignored. There are likely many instances of recipe, but they will all behave in the same way. We say the behavior is common to the class Recipe Since earlier our goal was to identify behavior, we ignored this distinction and concentrated on prototypical objects Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
209
Coupling and Cohesion The separation of tasks into the domains of different components should be guided by the concepts of coupling and cohesion Cohesion is the degree to which the tasks assigned to a component seem to form a meaningful unit. Want to maximize or minimize cohesion? Coupling is the degree to which the ability to fulfill a certain responsibility depends upon the actions of another component. Want to maximize or minimize coupling? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
210
Coupling and Cohesion Students in a class were asked to write a large program (~ 1000 lines). One student’s entire program consisted of a single main() function int main() { }
211
Coupling and Cohesion The student was told by the instructor that he needed to improve the program’s modularity Student broke up code in main() arbitrarily, first 25 lines to function/module 1, next 25 lines to function/module 2, … int main() { }
212
Coupling and Cohesion Cohesion is a measure of how well the parts of a component “belong together” It is a property or characteristic of an individual module Cohesion is strong if all parts are needed for the functioning of other parts A method is cohesive when it does only a single, precise task. If you have trouble naming a method, would that suggest weak or strong cohesion? Strong cohesion promotes maintainability and adaptability by limiting the scope of changes to a small number of components
213
Coupling and Cohesion Coupling is a measure of the strength of the interconnections between system components It is a property of a collection of modules Coupling is tight between components if they depend heavily on one another (e.g., there is a lot communication among them) Coupling is loose if there are few dependencies between components Loose coupling promotes maintainability and adaptability since changes in one components are less likely to affect other ones
214
Interface and Implementation
We have characterized software components by what they can do The user of a software component need only know what it does, not how it does it “Ask not what you can do to a data structure, ask instead what your data structures can do for you” Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
215
Two views of a Software System
This naturally leads to two views of a software system The term information hiding is used to describe the purposeful hiding of implementation details Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
216
The Unified Modeling Language
Several different notations for describing object-oriented designs were proposed in the 1980s and 1990s The Unified Modeling Language (UML) is an integration of those notations It describes notations for a number of different models that may be produced during OO analysis and design It is now a de facto standard for OO modelling
217
History of OOAD leading to UML
1970 First object-oriented languages (Simula-67, Smalltalk) 1980 More than 50 different OOAD languages cause users trouble to find complete and appropriate tools 1992 New iterations of methods appear Booch’93 (Grady Booch), OOSE (Ivar Jacobson), OMT-2 (James Rumbaugh) 1995 Unification, UML 0.9 by Booch and Rumbaugh 1997 Standardization, UML 1.1 by Booch, Rumbaugh, and Jacobson Object Management Group (OMG) adapts UML as OOAD standard
218
History of UML
219
UML Diagrams
220
Diagrams and Process
221
Diagrams and Process
222
Diagrams and Process
223
Diagrams and Process
224
Diagrams and Process
225
UML Class Diagrams Class diagrams describe the types of objects in the system and the various kinds of static relationships that exist among them There are 2 principal kinds of static relationships: Associations “A customer may rent a number of videos” Subtypes “A student is a kind of person” Class diagrams also show the attributes and operations of a class and the constraints that apply to the way objects are connected
226
UML Class Diagrams The main symbols shown on class diagrams are
Classes represent the types of data themselves Attributes are simple data found in classes and their instances Operations represent the functions performed by the classes and their instances Associations represent linkages between instances of classes Generalizations group classes into inheritance hierarchies
227
Classes A class is represented as a box with name of the class inside
The diagram may also show the attributes and operations A class can be drawn at several different levels of detail
228
Classes
229
Associations and Multiplicity
An association is used to show how instances of two classes are related to each other (i.e., will reference each other) Symbols indicating multiplicity are shown at each end of the association
230
Labelling associations
Each association can be labelled, to make explicit the nature of the association. There are 2 types of labels: association names should be a verb or verb phrase Direction of association can be clarified by showing a little arrow role names
231
Analyzing and validating associations
Many-to-one A company has many employees An employee can only work for one company This company will not store data about the moonlighting activities of employees! A company can have zero employees E.g. a ‘shell’ company It is not possible to be an employee unless you work for a company worksFor Employee 1 * Company
232
Analyzing and validating associations
Many-to-many A secretary can work for many managers A manager can have many secretaries Secretaries can work in pools Managers can have a group of secretaries Some managers might have zero secretaries Is it possible for a secretary to have, perhaps temporarily, zero managers?
233
Analyzing and validating associations
One-to-one For each company, there is exactly one board of directors A board is the board of only one company A company must always have a board A board must always be of some company 1
234
Analyzing and validating associations
Avoid unnecessary one-to-one associations Avoid this Do this
235
A more complex example A booking is always for exactly one passenger
no booking with zero passengers a booking could never involve more than one passenger A passenger can have any number of bookings a passenger could have no bookings at all a passenger could have more than one booking
236
Association classes Sometimes, an attribute that concerns two associated classes cannot be placed in either of the classes The following are equivalent
237
Object-Oriented Programming & Design Lecture 10
238
Reflexive Associations
It is possible for an association to connect a class to itself
239
Directionality in Associations
Associations are by default bi-directional It is possible to limit the direction of an association by adding an arrow at one end In a specification view this would indicate that a Day has a responsibility to tell which notes it is associated with, but a Note has no corresponding ability to tell which day it is associated with In an implementation view, one would indicate, that Day contains pointer(s) to Note(s), but a Note would not point to any Day
240
Generalization Specializing a superclass into two or more subclasses. They must follow the isa rule Our idealization of inheritance is captured in a simple rule-of-thumb. Try forming the English sentences ``An A is-a B''. If it “sounds right” to your ear, then A can be made a subclass of B A dog is-a mammal, and therefore a dog inherits from mammal A car is-a engine sounds wrong, and therefore inheritance is not natural but a car has-a engine
241
Generalization Represented using a small triangle pointing to the superclass The discriminator is a label that describes the criteria used in the specialization
242
Generalization Generalization captures similarities between several classes in a superclass. Specialization refines and adds differences in subclasses
243
Inheritance is both Extension and Contraction
Because the behavior of a child class is strictly larger than the behavior of the parent, the child is an extension of the parent (larger) Because the child can override behavior to make it fit a specialized situation, the child is a contraction of the parent (smaller)
244
Avoiding Unnecessary Generalizations
Inappropriate hierarchy of classes, which should be instances
245
Handling Multiple Discriminators
What about sharks?
246
Handling Multiple Discriminators
Creating higher-level generalization Results in duplication of features Another possible solution is multiple inheritance. However, it adds too much complexity and is not supported by many OOP languages (e.g., Java, C++) The platypus, a difficult case for single inheritance Why? Egg-laying mammal
247
Avoiding Having Instances Change Class
An instance should never need to change class How to solve this problem?
248
More Advanced Features: Aggregation
Aggregations are special associations that represent ‘part-whole’ relationships The ‘whole’ side is often called the assembly or the aggregate This symbol is a shorthand notation association named isPartOf
249
More Advanced Features: Aggregation
Example: “A CPU is part of a computer” Example: “A car has an engine and doors as its parts”
250
When to Use an Aggregation
As a general rule, you can mark an association as an aggregation if the following are true You can state that the parts ‘are part of’ the aggregate or the aggregate ‘is composed of’ the parts When something owns or controls the aggregate, then they also own or control the parts
251
When to Use Aggregation
Aggregation vs. attributes Attributes describe properties of objects (e.g., speed, price, length) Aggregation describe assemblies of objects Aggregation vs. association Is a company an aggregation over its employees or is it an association between its employees?
252
Composition A composition is a strong kind of aggregation
if the aggregate is destroyed, then the parts are destroyed as well A one-to-one composition often corresponds to a complex attribute. Two alternatives for addresses (i.e., as an attribute or as a composition)
253
Interfaces An interface is a (abstract) class with no implementation
An interface is implemented (refined) by (different) classes Example: A portable text editor displays its windows using a window interface that is implemented differently for Windows 95 and Mac OS
254
Abstract Classes An abstract class is a class without a (full) implementation Some methods are deferred (i.e., they are not implemented) The deferred methods are implemented by subclasses only Example: The window move operation is implemented by using hide and show methods which are implemented by subclasses
255
Example Class Diagram EXAMPLE: UML class diagram for airline reservation system (done in class)
256
How to Use Class Diagrams
Class diagrams are the backbone of nearly all object-oriented methods. Especially they facilitate code generation The trouble with class diagrams and their rich notation is that they are extremely detailed and therefore confusing Do not try to use all the notations available to you, if you do not have to Don’t draw diagrams for everything; instead concentrate on the key areas
257
Object-Oriented Programming & Design Lecture 11
258
Operator Overloading Most C++ operators can be overloaded
Overloaded operators are implemented using the C++ keyword operator There are some characteristics of the operators that cannot be changed when overloading them New operator names cannot be introduced Builtin operators cannot be overriden Operator precedences cannot be changed Operator associativity cannot be changed The number of operator parameters cannot be changed
259
Operator Overloading Handout #2
Notice that the Timer class contains an overloaded addition operator, which is a binary operator In the addition operator of Timer, the receiver of the message is the left (first) argument of “+”, and the argument is the second argument of “+”
260
Global vs. Method Operators
Instead, one could defined the previous overloaded operator as a global function rather than as a method Timer operator+(const Timer& t1, const Timer& t2) { … } Notice the difference between the global and the method definition: the first argument is missing in the method version…or is it? this serves as the first (left) argument of the operator this is a builtin, self-referential identifier; it contains the address of the receiving object In such a case, an operator call such as time1 + time2 is a message sent to the Timer instance time1
261
Global vs. Method Operators
Overloaded operators can be called in either operator form or functional form time0 = time1 + time2; // operator form time0 = time1.operator+(time2) // functional form The same rules hold for unary operators. For example, consider the “not” operators (i.e., “!”) int operator!(const Timer& t); // as global function int Timer::operator!(void) const; // as method Equivalent calls to overloaded operator ! if (!time1) … if (time1.operator!()) …
262
The Subscripting Operator
The second example of handout #2 illustrates an implementation of an overloaded subscripting operator (i.e., “[]”) Here is an example that uses it IntArray c1(5); for(int i=0; i<5; i++) { c1[i] = i; cout << c1[i] << endl; }
263
The Function Call Operator
The second example of handout #2 also illustrates an implementation of an overloaded function call operator (i.e., “()”) Here is an example that uses it IntArray c1(5); // … for(int i=0; i<5; i++) cout << c1() << endl; The function call operator can be defined with zero or more parameters in its parameter list
264
Conversion Operators A conversion operator converts an instance of the class of which it is a member to an instance of a builtin class (type) Timer::operator int(void) { return hours*3600+minutes*60+int(seconds); } Conversion operators have no return type specified explicitly since the name of the operator specifies the return type. They also always have a void parameter list
265
Overloaded Operator Q&A
Q: What if one wants to use objects as conditions? For example: if (time1) … if (!time1) … A: Define these operators as the methods: operator int(void); int operator!(void);
266
Overloaded Operator Q&A
Q: What if one wants to overload both prefix and infix ++? A: In the C++ standard, the two are distinguished as illustrated in the following examples
267
Prefix Overloaded Method
Timer Timer::operator++(void) { if (++seconds >= 60.0) { minutes++; seconds -= 60.0; } if (minutes >= 60) { hours++; minutes -= 60; return *this;
268
Postfix Overloaded Method
Timer Timer::operator++(int i) { Timer temp = *this; if (++seconds >= 60.0) { minutes++; seconds -= 60.0; } if (minutes >= 60) { hours++; minutes -= 60; return temp; WARNING! Since no actual value is sent to the int parameter, do not use the parameter in the method’s code!
269
Object-Oriented Programming & Design Lecture 12
270
UML Diagrams
271
Interaction Diagrams Interaction diagrams are used to model the dynamic aspects of a software system They help you to visualize how the system runs An interaction diagram is often built from a use case and a class diagram The objective is to show how a set of objects accomplish the required interactions with an actor
272
Interactions and Messages
Interaction diagrams show how a set of actors and objects communicate with each other to perform The steps of a use case, or The steps of some other piece of functionality The set of steps, taken together, is called an interaction Interaction diagrams can show several different types of communication E.g. method calls, messages send over the network These are all referred to as messages
273
Elements Found in Interaction Diagrams
Instances of classes Shown as boxes with the class and object identifier underlined Actors Use the stick-person symbol as in use case diagrams Messages Shown as arrows from actor to object, or from object to object
274
Creating Interaction Diagrams
You should develop a class diagram and a use case model before starting to create an interaction diagram There are two kinds of interaction diagrams: Sequence diagrams Communication diagrams
275
Sequence Diagrams Sequence Diagram Class Diagram
276
Sequence Diagrams A sequence diagram shows the sequence of messages exchanged by the set of objects performing a certain task The objects are arranged horizontally across the diagram An actor that initiates the interaction is often shown on the left The vertical dimension represents time A vertical line, called a lifeline, is attached to each object or actor The lifeline becomes a broad box, called an activation box during the live activation period A message is represented as an arrow between activation boxes of the sender and receiver A message is labelled and can have an argument list and a return value
277
Sequence Diagrams Same example but with more details
278
Sequence Diagrams If an object’s life ends, this is shown with an X at the end of the lifeline
279
Exercise Suppose that we are developing a loan processing system and we have identified the following use case: Use case: Submit Loan Request Actors: Applicant, Credit Bureau Steps: 1. An applicant completes and submits a loan application to the bank via the Internet. 2. The system validates the information on the loan application, checking that it is correct and as complete as possible. 3. The system forwards a loan request to an external credit bureau for a credit report on the applicant. 4. The system calculates the applicant’s credit score based on the returned credit report. Draw a corresponding sequence diagram (DONE IN CLASS)
280
UML Diagrams
281
State Diagrams State diagrams are a technique to describe the behavior (i.e., state changes) of a single object according to events and messages which the object sends and receives How does an individual object interact with other objects? Reacting to events and to messages received by the object Triggering actions and sending messages to other objects
282
State Diagrams State diagrams are good at describing the behavior of an individual object across several use cases Draw state diagrams especially for classes that are not well understood and that need detailed description State diagrams are not very good at describing behavior that involves a number of objects collaborating together If you have to describe several objects, which are involved in a single use case, use interaction diagrams instead
283
States A state Represents the internal condition/state of an object for a certain period of time Corresponds to an interval of time between 2 events The response to events may depend on the state of an object Object creation comes together with an initial object state Object deletion may be related with (one or many) final states
284
Sample State Diagram
285
Events An event is something worth noticing at a point of time
A signal from one object to another (e.g., “delivered”) A message received by an object (e.g., “check item”) A certain date/time (e.g., “after 10 seconds” of being in a certain state or “at 31-dec-2000, 00:00”) Events may take arguments (e.g., “deliver to receiver: Customer”)
286
Transitions A transition represents a change of the internal condition/state of an object A transition is usually triggered (“fired”) by an event. Transitions without event label (“lambda transitions”) fire immediately Transitions fire instantly From exactly one state to another state or to itself (self-transition) and are not interruptible
287
Transitions
288
Guards A guard is a logical condition (i.e., value is either “true” or “false”) A guarded transition fires only if the guard resolves to “true” Since only one transition can be fired in a given state, guards are intended to be mutually exclusive for any event Events may be guarded
289
Guards
290
Exercise Draw a state diagram that shows the behavior of instances of the CourseSection class in the following class diagram: (DONE IN CLASS)
291
Object-Oriented Programming & Design Lecture 13
292
Chapter 4 Classes and Methods
293
Same Ideas, Different Terms
All OOP languages have the following concepts, although the terms they use may differ classes, object type, factory object instances, objects message passing, method lookup, member function invocation, method binding methods, member function, method function inheritance, subclassing Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
294
Encapsulation and Instantiation
Classes provide a number of very important capabilities Encapsulation - The purposeful hiding of information, thereby reducing the amount of details that need to be remembered/communicated among programmers A Service View - The ability to characterize an object by the service it provides, without knowing how it performs its task Instantiation - The ability to create multiple instances of an abstraction Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
295
Internal and External Views
As we noted in the last chapter, encapsulation means there are two views of the same system. The outside, or service view, describes what an object does The inside, or implementation view, describes how it does it Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
296
Behavior and State A class can also be viewed as a combination of behavior and state Behavior: The actions that an instance can perform in response to a request. Implemented by methods State: The data that an object must maintain in order to successfully complete its behavior. Stored in instance variables (also known as data members, or data fields) Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
297
Class Definitions We will use as running example the class definition for a playing card abstraction, and show how this appears in several languages Languages considered in the book include Java, C++, C#, Delphi Pascal, Apple Pascal, Ruby, Python, Eiffel, Objective-C and Smalltalk Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
298
A Typical Example, Class Definition in C++
Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
299
Visibility Modifiers The terms public and private are used to differentiate the internal and external aspects of a class public features can be seen and manipulated by anybody -- they are the external (interface or service) view private features can be manipulated only within a class. They are the internal (implementation) view Typically methods are public and data fields are private, but either can be placed in either category Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
300
A C# Class Definition C# class definitions have minor differences, no semicolon at the end, enum cannot be nested inside a class, and visibility modifiers are applied to methods and data fields individually Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
301
Java Class Definition Java also applied visibility modifiers to each item individually. Does not have enumerated data types, uses symbolic constants instead Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
302
Static and Final Notice how symbolic constants are defined in Java
static means that all instance share the same value. One per class. Similar meaning in many languages final is Java specific, and means it will not be reassigned. (C++ has const keyword that is similar, although not exactly the same). Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
303
Pascal Dialects We will consider two dialects of Pascal, both descended from the earlier language Apple Object Pascal, defined by Apple Computer, once widely used on the Macintosh, now much less commonly used Delphi Pascal, defined by Borland on the PC, still fairly widely used on that platform (called Kylix on the Linux platform) Many similarities due to the common heritage, but some important differences Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
304
Class Definition in Apple Object Pascal
No explicit visibility modifiers (will later see syntax for methods) Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
305
Delphi Pascal Slightly different syntax, must name parent class, has visibility modifier, requires the creation of a constructor Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
306
Smalltalk Smalltalk doesn’t have a textual description for classes, but instead you define classes in a visual interface (revolutionary idea in 1980, but now Visual Basic and Delphi programmers are used to similar facilities) Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
307
Methods Although syntax will differ depending upon language, all methods have the following A name that will be matched to a message to determine when the method should be executed A signature, which is the combination of return type and argument types. Methods with the same name can be distinguished by different signatures A body, which is the code that will be executed when the method is invoked in response to a message Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
308
An Example, from C# Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
309
Constructor A constructor is a method that is used to initialize a newly constructed object. In C++, Java, C# and many other languages it has the same name as the class Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
310
Accessor (or getter) Methods
An accessor (or getter) is a method that simply returns an internal data value Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
311
Why Use an Accessor? There are many reasons why an accessor is preferable to providing direct access to a data field You can make the data field read-only It provides better documentation that the data field is accessible It makes it easier to later change the access behavior (count number of accesses, whatever) Some conventions encourage the use of a name that begins with get, (as in getRank()), but this is not universally followed Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
312
Setters (or mutators) A setter (sometimes called a mutator method) is a method that is used to change the state of an object Mutators are less common than accessors, but reasons for using are similar Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
313
Constant Data Fields Some languages allow data fields to be declared as constant (const modifier in C++, final in Java, other languages have other conventions). Constant data fields can be declared as public, since they cannot be changed Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
314
Order of Methods For the most part, languages don't care about the order that methods are declared. Here are some guidelines List important methods first Constructors are generally very important, list them first Put public features before private ones Break long lists into groups List items in alphabetical order to make it easier to search Remember that class definitions will often be read by people other than the original programmer. Remember the reader, and make it easy for them Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
315
Separation of Definition and Implementation
In some languages (such as C++ or Object Pascal) the definition of a method can be separated from its implementation. They may even be in a different file (e.g., the “header” file and the “implementation” file) Notice need for fully qualified names Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
316
Considerations in Method Definitions
In C++ you have a choice to define a method in the class interface, or separately in an implementation file. How do you decide? Readability. Only put very small methods in the class definition, so that it is easier to read Semantics. Methods defined in class interface may (at the discretion of the compiler) be expanded in-line. Another reason for only defining very small methods this way Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
317
Variations on Classes We will consider a few of the mostly language-specific variations on the idea of a class Methods without classes in Oberon Interfaces in Java (methods without implementations) Nested classes in Java and C++ Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
318
Methods without Classes in Oberon
Oberon does not have classes, per se, but allows methods to be defined as a funny type of function Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
319
Interfaces in Java An interface is like a class, but it provides no implementation. Later, another class declare that it supports the interface, and it must then give an implementation. We will have much more to say about interfaces later after we discuss inheritance Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
320
Inner or Nested Classes
Some languages (C++ or Java) allow a class definition to be given inside another class definition. Whether the inner class can access features of the outer class is different in different languages Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
321
Object-Oriented Programming & Design Lecture 14
322
Inheritance in C++ Base classes do not keep track of the classes derived from them. Rather, derived classes keep track of their base class(es) Handout #3 illustrates inheritance in C++ In this example, vector is the base class of vector3D (i.e., vector3D is derived from vector) Note the keyword public that appears just before the name of the base class in the derived class definition Also note that the data members of the base class are declared with a visibility level we have not discussed before: protected
323
Base Class Visibility In the example code given in handout #3, the base class is specified as a public base class. However, a base class can be declared as protected or private instead If no visibility is specified for a base class, the default visibility is private
324
Base Class Visibility The visibility of the inherited members is determined by these rules: public, protected, and private members of a public base class are inherited as public, protected, and private, respectively public, protected, and private members of a protected base class are inherited as protected, protected, and private, respectively public, protected, and private members of a private base class are inherited as private Thus, the visibility of the base class specifies the “minimum encapsulation” (i.e., the greatest visibility
325
Message Passing & Inheritance
When a message is passed to an object First check to see if a method defined in the object’s class can be used. If so, use that definition If not, pass the message to the parent class, and so on, until either an applicable method is found or the top of the inheritance hierarchy is reached
326
The Effects of Inheritance
Recall that the constructors of data members are executed before the constructor of the class containing them. The same can be said about the constructor of the base class Also recall that the destructors of data members are executed after the destructor of the class containing them. This is true for the destructor of the base class as well
327
A Day in the Life … part II
The order of events now becomes Creation (allocation) Base class constructors are called Component constructors are called Constructor is called Instance is manipulated Destructor is called Component destructors are called Base class destructors are called Destruction (deallocation)
328
A Day in the Life … part II
For example class lightSource { ... }; class bulb: public lightSource { string manufacturer; dateSpan expectedLife; ...}; The order of constructor execution is lightSource string (for manufacturer) dateSpan (for expectedLife) bulb The order of destructor execution is for vector3D in handout #3 ?
329
More on Inheritance Earlier it was said that if the constructor of a class does not explicitly call a constructor for a data member, then the default constructor of that data member will be called This also holds true for the base class constructor: if the base class has a default constructor, then there is no need to reference it in the derived class constructor However, one can choose explicitly which constructor should be called. This is illustrated in handout #3
330
Member Location Methods are located in classes, not in objects
That is, there is only one copy of each method, shared by all instances of the class Although all data members are defined in classes, they have two possible physical locations Instance variables are located within an object (i.e., within an instance of the class) Class variables are located within the class
331
Member Location Here is an example of instance and class variables
Suppose that one wants to represent a class of objects named StFXPhone The area code is a class variable, since a single value applies to all telephones on campus The prefix and line numbers are instance variables, since a given prefix/line number pair applies only to a particular telephone Why use class variables? They reduce data redundancy
332
Class Variables in C++ By default, data members are instance variables
To transform a data member into a class variable, one declares it with the static modifier Though class variables are declared within the class interface, they must be initialized globally
333
Class Variables in C++ Here is the interface of a class that contains a class variable class computer { float speed; ... static string brand; // class variable public: };
334
Class Variables in C++ And here is the initialization of the class variable // Initialize the class variable string computer::brand = “IBM”;
335
Class Variables in C++ Example: Write a StFXPhone class that has 2 class variables: one for the area code and another for the number of objects (i.e., phone numbers) that have been created
336
Object-Oriented Programming & Design Lecture 15
337
Chapter 8 Inheritance and Substitution
338
Abstract Idea of Inheritance
We motivated the idea of inheritance with a hierarchy of categories: Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
339
Practical Meaning of Inheritance
Data members in the parent are part of the child Behavior defined in the parent are part of the child Note that private aspects of the parent are part of the child, but are not accessible within the child class Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
340
Private, Public and Protected
There are now three levels of visibility modifiers: private: accessible only within the class definition (but memory is still found in the child class, just not accessible) public: accessible anywhere protected: accessible within the class definition or within the definition of child classes Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
341
Inheritance is both Extension and Contraction
Because the behavior of a child class is strictly larger than the behavior of the parent, the child is an extension of the parent (larger) Because the child can override behavior to make it fit a specialized situation, the child is a contraction of the parent (smaller) This interplay between inheritance and overriding, extension and contraction, is what allows object-oriented systems to take very general tools and specialize them for specific projects. This interplay is ultimately the source of a great deal of the power of OOP Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
342
The is-a Rule Our idealization of inheritance is captured in a simple rule-of-thumb Try forming the English sentences “An A is-a B”. If it “sounds right” to your ear, then A can be made a subclass of B A dog is-a mammal, and therefore a dog inherits from mammal A car is-a engine sounds wrong, and therefore inheritance is not natural but a car has-a engine Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
343
Reuse of Code, Reuse of Concept
Why do we use inheritance? Basically there are two major motivations: Reuse of code. Methods defined in the parent can be made available to the child without rewriting. Makes it easy to create new abstractions Reuse of concept. Methods described in the parent can be redefined and overridden in the child. Although no code is shared between parent and child, the concept embodied in the definition is shared Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
344
Syntax for Inheritance
Languages use a variety of different syntax to indicate inheritance class Wall : public GraphicalObject -- c++ class Wall extends GraphicalObject -- Java class Wall : GraphicalObject -- C# (defclass Wall (GraphicalObject)()) -- CLOS type Wall = object (GraphicalObject) -- Object Pascal class Wall < GraphicalObject -- Ruby Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
345
Trees vs Forests There are two common views of class hierarchies:
All classes are part of a single large class hierarchy. Thus, there is one class that is the original ancestor of all other classes. Smalltalk, Java and Delphi Pascal do this Classes are only placed in hierarchies if they have a relationship - results in a forest of many small hierarchies, but no single ancestor. C++, Objective-C, and Apple Object Pascal do this Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
346
A portion of the Little Smalltalk Hierarchy
Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
347
An Argument for Substitution
Consider the following argument: Instances of the subclass must possess all data areas associated with the parent class Instances of the subclass must implement, through inheritance at least (if not explicitly overridden) all functionality defined for the parent class (they can also define new functionality, but that is unimportant for the present argument) Thus, an instance of a child class can mimic the behavior of the parent class. It therefore seems reasonable that a variable declared as a parent, should be able to hold a value generated from the child class Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
348
Principle of Substitution
If we have two classes, A and B, such that class B is a subclass of class A, it should be possible to substitute instances of class B for instances of class A in any situation and with no observable effect Note: The principle of substitutability is sometimes called Liskov substitutability, since one of the first people to describe the idea was Barbara Liskov, of MIT. Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
349
Subclass vs Subtype Of course, the problem with this argument is that a child class can override a method and make arbitrary changes. It is therefore useful to define two separate concepts To say that A is a subclass of B merely asserts that A is formed using inheritance To say that a is a subtype of B asserts that A preserves the meaning of all the operations in B It is possible to form subclasses that are not subtypes; and (in some languages at least) form subtypes that are not subclasses Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
350
The two “subs” A class A is a subtype of a class B if the principle of substitution holds for the relationship between the classes A class A is a subclass of a class B is the substitution principle may or may not hold for the relationship between the classes
351
Interfaces and Abstract Classes
An interface is similar to a class, but does not provide any implementation. A child class must override all methods. A middle ground is an abstract class. Here some methods are defined, and some (abstract methods) are undefined. A child class must fill in the definition for abstract methods An interface is like an abstract class in which all methods are abstract. In C++ an abstract method is called a pure virtual method abstract class Window { ... abstract public void paint(); // child class must redefine } Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
352
Forms of Inheritance Many types of inheritance are given their own special names. We will describe some of these specialized forms of inheritance Specialization Specification Construction Generalization or Extension Limitation Variance Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
353
Specialization Inheritance
By far the most common form of inheritance is for specialization Each child class overrides a method inherited from the parent in order to specialize the class in some way Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
354
Specification Inheritance
If the parent class is abstract, we often say that it is providing a specification for the child class, and therefore it is specification inheritance (a variety of specialization inheritance) Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
355
Inheritance for Construction
If the parent class is used as a source for behavior, but the child class has no is-a relationship to the parent, then we say the child class is using inheritance for construction An example might be subclassing the idea of a Set from an existing List class Generally not a good idea, since it can break the principle of substituability, but nevertheless sometimes found in practice Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
356
Inheritance for Generalization or Extension
If a child class generalizes or extends the parent class by providing more functionality, but does not override any method, we call it inheritance for generalization The child class doesn't change anything inherited from the parent, it simply adds new features Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
357
Inheritance for Limitation
If a child class overrides a method inherited from the parent in a way that makes it unusable (for example, issues an error message), then we call it inheritance for limitation Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
358
Inheritance for Variance
Two or more classes that seem to be related, but it is not clear who should be the parent and who should be the child Example: Mouse and TouchPad and JoyStick Better solution, abstract out common parts to new parent class, and use subclassing for specialization Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
359
Benefits of Inheritance
Software Reuse Code Sharing Improved Reliability Consistency of Interface Rapid Prototyping Information Hiding Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
360
Cost of Inheritance Execution speed Program size
Message Passing Overhead Program Complexity This does not mean you should not use inheritance, but rather than you must understand the benefits, and weigh the benefits against the costs Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
361
Object-Oriented Programming & Design Lecture 16
362
Chapter 10 Subclasses and Subtypes
363
Subtype, Subclass and Substitution
The distinction between subtype and subclass is important because of their relationship to substitution Recall the argument that asserted a child class has the same behavior as the parent, and thus a variable declared as the parent class should in fact be allowed to hold a value generated from a child class But does this argument always hold true? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
364
Subtypes What is wanted here is something like the following substitution principle: If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2, then S is a subtype of T. [Liskov 1988] Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
365
What is a type? What do we mean when we use the term (data) type in describing a programming language? A set of values (the type int, for example, describes to ) A set of operations (we can do arithmetic on ints, not on booleans) A set of properties (if we divide 8 by 5 we are not surprised when the result is 1, and not 1.6) What about when we consider classes (or interfaces) as a system for defining types? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
366
The Problem of Defining Types
Consider how we might define a Stack ADT Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
367
The Problem of Defining Types
Notice how the interface itself says nothing about the LIFO property, which is the key defining feature of a stack. Is the following a stack? This class definition satisfies the Stack interface but does not satisfy the properties we expect for a stack, since it violates the LIFO property for all but the most recent item placed into the stack Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
368
Syntax vs. Semantics Although not an exact correspondence, the issue of subclass vs. subtype is in some way similar to the more familiar language distinction between syntax and semantics Syntax deals with how a statement can be written, just as subclasses deal with how a class is declared Semantics deals with what a statement means, just as subtypes deal with how a child class preserves the meaning of a parent class Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
369
The Definition of Subtype
From this example we see that the properties that are key to the meaning of the Stack are not specified by the interface definition. And it is not that we were lazy; Java (like most other languages) gives us no way to specify the properties that an interface should satisfy Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
370
The Definition of Subtype
So now we can better understand the concept of a subtype A subtype preserves the meaning (purpose, or intent) of the parent The problem is that meaning is extremely difficult to define. Think about how to define the LIFO characteristics of the stack Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
371
The Substitution Paradox
There is a curious paradox that lies at the heart of most strongly typed object-oriented programming languages Substitution is permitted, based on subclasses. That is, a variable declared as the parent type is allowed to hold a value derived from a child type Yet from a semantic point of view, substitution only makes sense if the expression value is a subtype of the target variable If substitution only makes sense for subtypes and not for all subclasses, why do programming languages based the validity of assignment on subclasses? Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
372
The Undecidability of the Subtype Relationship
It is trivial to determine if one class is a subclass of another It is extremely difficult to define meaning (think of the Stack ADT), and even if you can it is almost always impossible to determine if one class preserves the meaning of another One of the classic corollaries of the halting problem is that there is no procedure that can determine, in general, if two programs have equivalent behavior There is simply no way that a compiler can ensure that a subclass created by a programmer is indeed a subtype Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
373
Is This a Problem? What does it take to create a subclass that is not a subtype? The new class must override at least one method from the parent It must preserve the type signatures But it must violate some important property of the parent Is this common? Not likely. But it shows you where to look for problem areas Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
374
Subtyping in C++ Subtyping in C++ is provided through inheritance
Suppose a class Circle is derived from a class Shape. Then, as mentioned before, a Circle object can be implicitly converted into a Shape object Circle circle; Shape shape = circle; This is called upcasting in C++ because you’re moving up in the class hierarchy What happens here is that shape loses all information about circle which isn’t contained within the Shape class (e.g., a radius data member). This is known as object slicing
375
Friends (not the TV show)
A friend function is a function that explicitly is given full access to the protected and private members of a class, even though it is not a member of that class (or of any of its derived classes) Friend functions violate the rules of encapsulation, so they should be used sparingly Two situations in which one would use friend functions are A need exists to provide a function with access to members of more than one class There is a need to pass all arguments through the argument list
376
Friends (not the TV show)
Friend functions can be either methods of another class or global functions Handout #4 contains a simple example in which the friend function would be justified If many methods of one class need direct access to the protected and private members of another class, the first class can be designated as a friend class to the second For example, in handout #4 one could change the declaration friend 3DPoint::transform(const Matrix&) const; to friend class 3DPoint;
377
Friends (not the TV show)
A friend function (or class) may be declared among the public, protected, or private members of the class to which it is a friend One should have strong justification for declaring friend functions One should have very strong justification for declaring friend classes Note: Since overloadings of the I/O operators must be implemented as nonmember (global) functions, they are usually made friends of the class friend ostream& operator<<(ostream& out, const Matrix& m)
378
Object-Oriented Programming & Design Lecture 17
379
Static and Dynamic Behavior
When we left off last time, we were able to derive new types from existing types, and we could upcast from a derived type to its base type This was useful because it allowed us to share some code However, it really didn’t give us the polymorphism we want to extract from similar types
380
Static and Dynamic Behavior
For example, suppose we have the following inheritance hierarchy class Shape { ... void draw(void) const; }; class Circle:public Shape{ class Rectangle:public Shape{ void draw(void) const; void draw(void) const; }; };
381
Static and Dynamic Behavior
Suppose we declared an array of shapes like this Shape* shapeList[3]; shapeList[0] = new Circle(...); // Upcast to Shape* shapeList[1] = new Square(...); // Upcast to Shape* shapeList[2] = new Rectangle(...); // Upcast to Shape* We might want a function to draw all of our shapes in the shape list void draw(int numShapes, Shape* shapeList[]) { for(int i=0; i<numShapes; i++) shapeList[i]->draw(); }
382
Static and Dynamic Behavior
Even though we created a Circle object, a Rectangle object, and a Square object, drawShapes only sees them as generic Shape objects There are different ways of solving this problem, and we’ll look at a couple of them
383
Type Fields One way to solve this polymorphism problem is to manually store the type within every Shape, Circle, or Rectangle object We could do this by defining an enumerated type, and marking each object in its constructor with its proper type However, this is very error prone and tends to lead to a lot of switch statements and casting throughout your code Write the drawShape function that uses type fields (DONE IN CLASS)
384
Static vs. Dynamic Type So far, we haven’t been able to break the bounds of the declaration type, or the static type, of an object The declared type of an object or an object pointer has been determining which method will be called The compiler pays no attention to the true type of the object – which is the type we provided when we allocated it with new. This is also called the object’s dynamic type
385
Chapter 11 Static and Dynamic Behavior
386
What do the terms Static and Dynamic Mean?
Much of the power of object-oriented languages derives from the ability of objects to change their behavior dynamically at run time In Programming languages Static almost always means fixed or bound at compile time, and cannot thereafter be changed Dynamic almost always means not fixed or bound until run time, and therefore can change during the course of execution Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
387
Static and Dynamic Typing
In a statically typed programming language (e.g., C++, Java, Pascal), variables have declared types -- fixed at compile time In a dynamically typed programming language (e.g., Smalltalk, Python), a variable is just a name. Types are associated with values, not variables. A variable can hold different types during the course of execution Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
388
Arguments For and Against
Static and Dynamically typed languages have existed as long as there have been programming languages. Arguments for and against: Static typing allows better error detection, more work at compile time and hence faster execution time Dynamic typing allows greater flexibility, easier to write (for example, no declaration statements) Both arguments have some validity, and hence both types of languages will continue to exist in the future Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
389
The Polymorphic Variable
The addition of object-oriented ideas in statically typed languages adds a new twist. Recall the argument for substitution: an instance of a child class should be allowed to be assigned to a variable of the parent class Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
390
Static Class and Dynamic Class
In a statically typed language we say the class of the declaration is the static class for the variable, while the class of the value it currently holds is the dynamic class Most statically typed OO languages constrain the dynamic class to be a child class of the static class Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
391
Importance of Static Class
In a statically typed object-oriented language, the legality of a message is determined at compile time, based on the static class A message can produce a compile error, even if no run-time error could possibly arise Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
392
Binding Times The binding time of a function call is when the call is bound to a specific function implementation There generally are two binding times: static binding and dynamic binding Static binding (also known as early binding) is when the function choice is based on the characteristics of the variable (i.e., the type of the variable) Static binding generally takes place at compile time Function overloading and overriding in C++ are examples of static binding
393
Binding Times Dynamic binding (also known as late binding) is when the function choice is based on the dynamic characteristics of the variable (i.e., the type of the data in the variable) Dynamic binding is deferred until run time In the previous example, if one sends a draw message to an instance of Rectangle, Circle, or Square, one would want the appropriate implementation of draw to be executed However, if at compile time one knows only that the receiving object is “an instance of a Shape subclass, to be determined at run time”, static binding cannot be used. In this case, dynamic binding is used Dynamic binding is a powerful by dangerous tool To eliminate the danger of run time errors in C++, dynamic binding has been limited to virtual functions
394
Virtual Functions The way to retain the behavior of the instantiated type is through the use of virtual functions To declare a method to be a virtual function, you simply use the virtual keyword when declaring the method in the class definition When you call a function, it will check the dynamic type of the object before choosing which function to call – this process is reification
395
Virtual Functions For example, we could declare our Shape, Circle, and Rectangle classes as follows class Shape { ... virtual void draw(void) const; }; class Circle:public Shape{ class Rectangle:public Shape{ virtual void draw(void) const; virtual void draw(void) const; }; };
396
Virtual Functions Now we get the polymorphic behavior we want
Shape* shapeList[maxShapes]; shapeList[0] = new Circle(...); // Upcast to Shape* shapeList[1] = new Square(...); // Upcast to Shape* shapeList[2] = new Rectangle(...); // Upcast to Shape* shapeList[0]->draw(); // Calls Circle::draw() shapeList[1]->draw(); // Calls Square::draw() shapeList[2]->draw(); // Calls Rectangle::draw()
397
Virtual Functions It is important that you declare the function to be virtual throughout your class hierarchy, or its behavior will be quite unexpected A virtual method can call a non-virtual method and vice-versa Overloaded operator functions can be virtual functions, but static methods can’t
398
Virtual Functions A constructor cannot be a virtual function because it needs to know the exact type to create However, a destructor can be declared as virtual, and generally should be virtual functions may not seem significant at first, but they enable a ton of code reuse when using class hierarchies
399
Object-Oriented Programming & Design Lecture 18
400
Virtual Functions To see more examples of how virtual functions are used, let’s develop another inheritance hierarchy: the base class is timeOfDay, and its derived class is timeOfYear This hierarchy is illustrated in handout #5 Both of these classes contain an implementation of the virtual method print
401
Virtual Functions Now let’s assume that we are given the following declarations timeOfDay tod(3, 45, 2.2); timeOfYear toy(30, 7, 14, 51.6); timeOfDay* tPtr1 = &tod; timeOfDay* tPtr2 = &toy; Then the statements tod.print(cout); toy.print(cout); will produce the output 3:45:2.2 30:7:14:51.6
402
Virtual Functions Because print is a virtual function, the statements
tPtr1->print(cout); tPtr2->print(cout); will also produce the output 3:45:2.2 30:7:14:51.6
403
Virtual Functions What would happen if we let the keyword virtual out of the example interfaces? The statements tPtr1->print(cout); tPtr2->print(cout); would produce the output 3:45:2.2 7:14:51.6
404
Diversity in the Workspace
One of the ways we can use virtual functions is to create an array of base class pointers and use it as an array of “elements” of diverse types Could this be done in ANSI C? Certainly! One could create an array of void* elements and point them to instances of various structures But how would one later know the types of the particular structure instances? Some possibilities include Point at a union of the possible structure types. Then, keep a flag to indicate the structure type of the data currently stored in the union Begin all structures with a flag to indicate its structure type; then, with lots of casting check the flag and treat the block of memory as the appropriate structure type
405
Diversity in the Workspace
Both of these solutions require the user to keep track of the type of the data. This is unnecessary when one uses virtual functions in C++ The only restriction is that all of the various types would have to be kept in the same inheritance hierarchy One might even want to define a method named something such as whatTypeAmI that determines the type of an instance for use in conditional statements
406
Virtual Functions & References
The example in handout #5 also illustrates how one would use virtual functions with reference parameters The base class timeOfDay has a friend function, the overloaded operator<< The second parameter of this function is a reference to a base class instance The overloaded operator then calls the appropriate version of print
407
Virtual Functions & References
For example, using the variables defined in the earlier example, the statements cout << tod << endl; cout << toy << end; will produce the output 3:45:2.2 30:7:14:51.6
408
Pure Virtual Functions
A class that is too generic to be instantiated is called an abstract class Some methods might be identified in an abstract class, but not implemented in that class A C++ method that is identified, but not implemented in a base class is called a pure virtual function
409
Pure Virtual Functions
A pure virtual function generally has a NULL implementation. For example virtual void print(ostream& cout) = 0; This NULL implementation is located in the interface of the class The declaration of a pure virtual function in a class forces the class to be an abstract class If a pure virtual function declared in a base class is not implemented in a derived class, then the derived class is an abstract class too
410
Constructors Can’t Be Virtual
Constructors aren’t inherited and can’t be virtual Constructors are very tightly bound up with a class and each class has its own unique set of constructors It is non-sensical to declare a constructor virtual since a constructor is always called by name (e.g., (timeOfDay(...), timeOfYear(...)) so there is no choice about which version to invoke timeOfYear& timeOfYear::operator=(const timeOfYear& t){ if(this != &t) { timeOfDay::operator=(t); // do rest of timeOfYear copying here } return *this;
411
operator= is not inherited either
This method is also very tightly coupled with a class Remember that, just like with constructors, if you don’t provide an overloading of operator=, a default one is automatically provided If you choose to implement your own version, you should invoke the parent class to do the parent’s part of the assignment
412
Virtual Destructors Normally, when one deletes an instance of a derived class (e.g., timeOfYear), the destructors of the derived class and those of all the ancestor classes are executed (in this case, the timeOfDay destructor) But let’s assume that we are given the following statement timeOfDay* tPtr1 = new timeOfYear(30,7,14,51.6); What happens when one executes the following statement? delete tPtr1;
413
Virtual Destructors Since the classes involved in the example do not have virtual destructors, only the timeOfDay destructor is executed! Further, if additional classes appeared in the hierarchy between timeOfYear and timeOfDay, their destructors would not be executed, either This behavior can lead to memory leaks and other unpleasantries, especially when dynamic memory or class variables are managed by the derived class A solution to the problem is the use of virtual destructors
414
Virtual Destructors A virtual destructor is simply a destructor that is declared as a virtual function If the destructor of a base class is declared as virtual, then the destructors of all its descendant classes become virtual, too (even though they do not have the same names)
415
Virtual Destructors In the example illustrated in handout #5, the derived class maintains a class variable that is used as an instance counter. The statement timeOfDay* tPtr1 = new timeOfYear(30,7,14,51.6); executes the constructors of timeOfDay and then timeOfYear, thus incrementing the class variable However, the statement delete tPtr1; executes only the destructor of timeOfDay Thus, the class variable does not get decremented
416
Virtual Destructors Rules of thumb for virtual destructors
If any class in a hierarchy manages class variables or dynamic memory, make its destructor virtual If none of the classes in a hierarchy have user-defined destructors, do not use virtual destructors
417
Pure Virtual Destructors
Ass odd as it may seem, there are times when one may want to define a pure virtual destructor. Why? One may want to force a class to be an abstract class though it has no pure virtual functions. A pure virtual destructor will do this It also could be the case that the class is already an abstract class, but one wants to assure that the destructors in the hierarchy are virtual
418
Pure Virtual Destructors
As one might expect, a pure virtual destructor for class timeOfDay would be declared as follows in the class interface virtual ~timeOfDay(void) = 0; However, unlike other pure virtual functions, one also must provide an empty implementation for pure virtual destructors timeOfDay::~timeOfDay(void){ }
419
Virtual Functions: Hidden Details
Instances of classes that have virtual functions must retain “behind the scenes” data to identify the class to which they belong. This information is used to look up appropriate method implementations at run time In C++, this data consists of a vtbl (virtual function table) pointer. The vtbl pointer points to an array of vptr (virtual function pointer) values (one sometimes sees the word functor used as a synonym for function pointer) Thus, when one defines virtual functions in a class, space and time overhead is incurred
420
Object-Oriented Programming & Design Lecture 19
421
Chapter 13 Multiple Inheritance
422
Inheritance as Classification
In one way, the is-a relationship is a form of classification E.g., A TextFile is a type of File so class TextFile inherits from class File File TextFile Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
423
Inheritance as Classification
But in the real world, most objects can be categorized in a variety of ways. A person can be a Male Professor Parent None of these are proper subsets of the other, and we cannot make a single rooted inheritance hierarchy out of them Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
424
Inheritance as Combination
Instead, real world objects are combinations of many nonoverlapping categories, each category contributing something to the result Note that we have not lost the is-a relationship; it still applies in each case Male Professor Parent Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
425
Multiple Inheritance Modeling this behavior in programs seems to call for the concept of multiple inheritance An object can have two or more different parent classes and inherit both data and behavior from each Male Professor Parent Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
426
Multiple Inheritance It wouldn't be an exaggeration to say that multiple inheritance has stirred more controversy and heated debates than has any other C++ feature Yet the truth is that multiple inheritance is a powerful and effective feature -- when used properly What is a good model?
427
Incomparable Complex Numbers
A portion of the Smalltalk class hierarchy things that can be compared to each other Object Boolean Magnitude Collection True False Char Number Point Set KeyedCollection Integer Float Fraction things that can perform arithmetic Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
428
Possible Solutions Make Number subclass of Magnitude, but redefine comparison operators in class Complex to give error message if used (e.g., subclassing for limitation) Don't use inheritance at all -- redefine all operators in all classes (e.g., flattening the inheritance tree) Use part inheritance, but simulate others (e.g., use Number, but have each number implement all relational operators) Make Number and Magnitude independent, and have Integer inherit from both (i..e, multiple inheritance) Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
429
Possible Solutions Magnitude Number Char Integer Complex
Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
430
Another Example – Walking Menus
A Menu is a structure charged with displaying itself when selected by the user A Menu maintains a collection of MenuItems Each MenuItem knows how to respond when selected A cascading menu is both a MenuItem and a Menu Adapted From: An Introduction to Object Oriented Programming, 3rd Edition, by Timothy Budd
431
Multiple Inheritance in C++
C++ supports multiple inheritance (i.e., a class may be derived from more than one base class) C++ syntax: class Derived: public Base1, public Base2, public Base3, protected Base4 { ... }; Example: class passengerVehicle { ... }; class trainCar { ... }; class passengerCar: public passengerVehicle, public trainCar { ... }; Handout #6
432
The Ambiguity Problem Circumstances: Let Derived be inherited from Base1 and Base2 All feature names inside Base1 are distinct All feature names inside Base2 are distinct All feature names inside Derived should be distinct Ambiguity problem: the same feature name X occurs both in Base1 and in Base2 The problem does not occur in single inheritance If the same feature name occurs both in Derived and in Base, then no ambiguity occurs. Why?
433
The Ambiguity Problem In handout #6, what would happen if we attempted to print the data members of derived by accessing them individually instead of using the overloaded operator<< cout << “Object derived contains:\n” << “Integer: “ << derived.getData() << “\nCharacter: “ << derived.getData() << “\nReal number: “ << derived.getReal() << “\n\n“;
434
Coincidental vs. Inherent Ambiguity
Coincidental ambiguity occurs when the duplicated names Base1::X and Base2::X are unrelated Ambiguity is a coincidence Same name, distinct entities Inherent ambiguity occurs when Base1 and Base2 derive from a common Base, in which X occurs Ambiguity is inherent Same name, same entity
435
Ambiguity Resolution Approaches
Forbid the inheritance as given. Force the designer of Base1 and/or Base2 to resolve the ambiguity Unreasonable: Good names are rare. In many cases, multiple inheritance marries together two distinct inheritance hierarchies, sometimes supplied by different vendors Impossible: In cases of repeated inheritance Force the designer of Derived to resolve all ambiguities In Eiffel, the compiler does not allow a class in which an ambiguity exists. The designer must rename all ambiguous features In C++, a good designer will override all ambiguous features. This is not always possible since one cannot override data members
436
Ambiguity Resolution in C++
Scenario An inherited function/data member is used (inside or outside the class) The compiler checks that the name is defined in exactly one (direct/indirect) base class Error message produced if name is defined in more than one class Ambiguity should be resolved before compilation can proceed Use qualified names (::) to specify exactly one derived member
437
Ambiguity Resolution in C++
In handout #6, if we wanted to print the data members of derived by accessing them individually instead of using the overloaded operator<<, we could use the scope resolution operator (::) to resolve the ambiguity cout << “Object derived contains:\n” << “Integer: “ << derived.Base1::getData() << “\nCharacter: “ << derived.Base2::getData() << “\nReal number: “ << derived.getReal() << “\n\n“; Drawbacks Client should be aware of implementation details Late detection of errors
Similar presentations
© 2025 SlidePlayer.com Inc.
All rights reserved.