CSCI 431 Lecture Notes - Examples of Exception Handling
and Introduction to OOP (Chapter 4)
Ada Exceptions Example
First Part: Package Specification - Sample_Functions
PACKAGE Sample_Functions IS
-- for illustrating both overloading and exceptions
FUNCTION Minimum(Value1 : Integer; Value2 : Integer) RETURN Integer;
FUNCTION Minimum(Value1 : Float; Value2 : Float) RETURN Float;
FUNCTION Factorial(N: Positive) RETURN Positive;
END Sample_Functions;
Second Part - Package Body for Sample_Functions
PACKAGE BODY Sample_Functions IS
-- Minimum of two integer values.
FUNCTION Minimum(Value1 : Integer; Value2 : Integer) RETURN Integer IS
Result : Integer;
BEGIN
IF Value1 < Value2 THEN
Result := Value1;
ELSE
Result := Value2;
END IF;
RETURN Result;
END Minimum;
-- Minimum of two Float values.
FUNCTION Minimum(Value1 : Float; Value2 : Float) RETURN Float IS
Result : Float;
BEGIN
IF Value1 < Value2 THEN
Result := Value1;
ELSE
Result := Value2;
END IF;
RETURN Result;
END Minimum;
-- factorial
FUNCTION Factorial(N: Positive) RETURN Positive IS
Result: Positive;
BEGIN
Result := 1;
FOR Count IN 1..N LOOP
Result := Result * Count;
END LOOP;
RETURN Result;
END Factorial;
END Sample_Functions;
Third Part - Sample Program to execute one of the above
functions
WITH Sample_Functions; USE Sample_Functions;
WITH Ada.Text_IO;
WITH Ada.Integer_Text_IO;
PROCEDURE Demo_Exceptions IS
-- Demonstrate exception handling
SUBTYPE Restricted IS Positive RANGE 1..10;
InputValue: Restricted;
OutputValue: Positive;
BEGIN
Ada.Text_IO.Put( Item => "Enter an integer from 1 to 10 > ");
Ada.Integer_Text_IO.Get( Item => InputValue);
Ada.Text_IO.New_Line;
OutputValue := Factorial(InputValue);
Ada.Integer_Text_IO.Put(Item => InputValue);
Ada.Text_IO.Put("! = ");
Ada.Integer_Text_IO.Put(Item => OutputValue);
Ada.Text_IO.New_Line;
EXCEPTION
WHEN Constraint_Error =>
Ada.Text_IO.Put( Item => "The input value is out of range.");
Ada.Text_IO.New_Line;
WHEN Ada.Text_IO.Data_Error =>
Ada.Text_IO.Put( Item => "The input value is not well-formed.");
Ada.Text_IO.New_Line;
END Demo_Exceptions;
Exceptions without leaving the program.
WITH Sample_Functions; USE Sample_Functions;
WITH Ada.Text_IO;
WITH Ada.Integer_Text_IO;
PROCEDURE Demo_Exceptions_2 IS
-- Demonstrate exception handling
SUBTYPE Restricted IS Positive RANGE 1..10;
InputValue: Restricted;
OutputValue: Positive;
BEGIN
FOR Count IN 1..5 LOOP
LOOP -- This loop is only to make the input robust.
BEGIN -- Block for exception handler
Ada.Text_IO.Put( Item => "Enter an integer from 1 to 10 > ");
Ada.Integer_Text_IO.Get( Item => InputValue);
EXIT; -- Leave Loop Only on Normal Input.
EXCEPTION
WHEN Constraint_Error =>
Ada.Text_IO.Put( Item => "The input value is out of range.");
Ada.Text_IO.New_Line;
WHEN Ada.Text_IO.Data_Error =>
Ada.Text_IO.Put( Item => "The input value is not well-formed.");
Ada.Text_IO.New_Line;
Ada.Text_IO.Skip_Line; -- Avoid infinite loop rereading line.
END; -- This is the end of the block for the exception handler.
END LOOP;
Ada.Text_IO.New_Line;
OutputValue := Factorial(InputValue);
Ada.Integer_Text_IO.Put(Item => InputValue);
Ada.Text_IO.Put("! = ");
Ada.Integer_Text_IO.Put(Item => OutputValue);
Ada.Text_IO.New_Line;
END LOOP;
END Demo_Exceptions_2;
Raising user-defined exceptions
The vecmanagement package (two files)
package VECMANAGEMENT is
subtype index is INTEGER range 0..INTEGER'LAST;
type vector is array(index range <>) of FLOAT;
IncompatDims : exception;
function "+" (u,v : in vector) return vector;
function "-" (u,v : in vector) return vector;
function "*" (u,v : in vector) return vector;
function "*" (x : in FLOAT; v: in vector) return vector;
end VECMANAGEMENT;
package body VECMANAGEMENT is
function "+" (u,v : in vector) return vector is
dim : constant INTEGER := u'LENGTH;
w : vector(1..dim);
begin
if v'LENGTH /= dim then raise IncompatDims ; end if;
for i in 1..dim loop w(i) := u(i) + v(i); end loop;
return w;
end "+";
function "-" (u,v : in vector) return vector is
dim : constant INTEGER := u'LENGTH;
w : vector(1..dim);
begin
if v'LENGTH /= dim then raise IncompatDims ; end if;
for i in 1..dim loop w(i) := u(i) - v(i); end loop;
return w;
end "-";
function "*" (u,v : in vector) return vector is
dim : constant INTEGER := u'LENGTH;
w : vector(1..dim);
begin
if v'LENGTH /= dim then raise IncompatDims ; end if;
for i in 1..dim loop w(i) := u(i) * v(i); end loop;
return w;
end "*";
function "*" (x : in FLOAT; v : in vector) return vector is
dim : constant INTEGER := v'LENGTH;
w : vector(1..dim);
begin
for i in 1..dim loop w(i) := x * v(i); end loop;
return w;
end "*";
end VECMANAGEMENT;
A program that handles the exception.
with vecmanagement; use vecmanagement;
with Ada.Float_Text_IO;
with Text_IO; use Text_IO;
procedure tryvecs is
a: vector(1..3);
b: vector(1..3);
c: vector(1..4);
begin
for i in 1..3 loop a(i) := Float(i); end loop;
for i in 1..4 loop c(i) := 1.0; end loop;
b := a + a;
for i in 1..3 loop
Ada.Float_Text_IO.Put(b(i));
New_Line;
end loop;
c := a + c;
Put("Tried that"); New_Line;
exception
when IncompatDims => Put("Incompatible sizes");
New_Line;
end tryvecs;
The output of the above program.
2.00000E+00
4.00000E+00
6.00000E+00
Incompatible sizes
Another Ada Exception Handling Example
with TEXT_IO; use TEXT_IO;
procedure GRADE_DISTRIBUTION is
package INTEGER_TEXT_IO is new INTEGER_IO(INTEGER);
use INTEGER_TEXT_IO;
FREQ: array (1..10) of INTEGER := (others => 0);
NEW_GRADE, INDEX, LIMIT_1, LIMIT_2 : INTEGER;
begin
loop
GET(NEW_GRADE);
INDEX := NEW_GRADE / 10 + 1;
begin -- block for the CONSTRAINT_ERROR handler
FREQ(INDEX) := FREQ(INDEX) + 1;
exception
when CONSTRAINT_ERROR =>
if NEW_GRADE = 100 then
FREQ(10) := FREQ(10) + 1;
else
PUT("ERROR -- new grade: ");
PUT(NEW_GRADE);
PUT(" is out of range");
NEW_LINE;
end if;
end; -- end of block for the CONSTRAINT_ERROR handler
end loop;
exception -- This handler includes all final computations
when END_OF_FILE =>
PUT("Limits Frequency");
NEW_LINE; NEW_LINE;
for INDEX in 0 .. 9 loop
LIMIT_1 := 10 * INDEX;
LIMIT_2 := LIMIT_1 + 9;
if INDEX = 9 then
LIMIT_2 := 100;
end if;
PUT(LIMIT_1);
PUT(LIMIT_2);
PUT (FREQ(INDEX + 1));
NEW_LINE;
end loop; -- for INDEX in 0 .. 9
end;
end GRADE_DISTRIBUTION;
C++ Exception Handling---A Simple Example First
void rational::setDenominator(int denom)
{
try
{
if (denom != 0)
denominatorValue = denom;
else
throw(denom);
}
catch (int d)
{
cerr << "Illegal denominator: " << denom << " using 1 instead"
<< endl;
denominatorValue = 1;
}
}
C++ Exception Handling---The Ada Example Above in C++
#include
void main()
{
int new_grade, limit_1, limit_2, freq[10]= {0,0,0,0,0,0,0,0,0}
short int eof_condition;
try
{
while (1)
{
if (!cin >> new_grade) // when cin detects eof
throw(eof_condition); // raise eof_condition
index = new_grade/10;
{
try
{
if (index < 0 || index > 9)
throw(new_grade);
freq[index]++;
} // end of inner try block
catch(int grade) // handler for index errors
{
if (grade == 100)
freq[9]++;
else
cout << "ERROR -- new grade: " << grade
<< " is out of range" << endl;
} // end catch
} // end block for inner try/catch pair
} // end while(1)
} // end outer try block
catch(short int junk) // handler for eof
{
cout << "Limits Frequency" << endl;
for (index=0; index<10; index++)
{
limit_1 = 10 * index;
limit_2 = limit_1 + 9;
if (index == 9)
limit_2 = 100;
cout << limit_1 << limit_2 << freq[index] << endl;
} // end for
} // end catch
} // end main
Chapter 4---OOP
A Little History
- Procedure-orientated programming was the most popular software
paradigm in the 1970's.
- subprograms and subprogram libraries
- Data-orientated programming focuses on Abstract Data
Types (ADT's)---languages that support ADT's are often called
object-orientated (OO) languages
- OO programming has its roots in SIMULA 67
- Introduced the notion of a class
- Not fully developed until Smalltalk 80
- Sometimes considered the first (and perhaps only) purely OO
programming language
- Executing a program can be described as a simulation of a
collection of objects that communicate with each other through
messages.
- Each object is an abstraction of a computer in that it stores and
manipulates data
Terminology
- ADT's and classes
- objects
- derived class or subclass
- parent class or superclass
- methods and messages
- message protocol or message interface
- X1access control
- public, private, and protected
- overriden methods
- instance methods and variables vs. class methods and variables
- single inheritance and multiple inheritance
- dynamic binding (a kind of polymorphism)
- constructor and destructor
Design Issues
- Exclusivity of objects
- Are subclasses subtypes?
- Implementation and interface inheritance
- Type checking and polymorphism
- Single and multiple inheritance
- Allocation and deallocation of objects
- Dynamic and static Binding
Exclusivity of objects
- In the purest OO model all types are classes. There is no
distinction between pre-defined and user defined classes. All
computation is accomplished through message passing.
- In imperative languages that support OO it is common to:
- Add classes to the existing type structure, or
- Leave the existing imperative type structure intact for primitive
types only
Are subclasses subtypes?
- Does an "is-a" relationship hold between a parent class and its
derived class?
- An is-a relationship would guarantee that a object of the derived
class could appear anywhere an object of the parent class was legal.
- In this case, subclasses can only add members and override methods in
"compatible ways"
Implementation and interface inheritance
- Should subclasses only see the interface of the parent classes?
- There are trade-offs:
- Granting access to subclasses can make programming of the
subclass more efficient
- It can also create dependencies that defeat the objective of
information hiding, e.g., changes to the parent class would
necessitate the recompilation of the derived class
Type checking and polymorphism
- In OO programming "polymorphism" refers to the use of polymorphic
pointers used to reference a method that has been overridden in a derived
object, even when the polymorphic pointer is declared to be a pointer
to the parent type.
- The issue here is when does type checking take place?
- Type checking (in a strongly typed language) includes checking
both parameters and return types
- This restricts the parameters and return types that can be used in
overriden methods
Single and multiple inheritance
- The issues in allowing multiple inheritance are complexity and
efficiency
- Complexity issues are concerned with such things as name conflicts
and maintenance
- Efficiency issues are not very important---only one additional
operation for each dynamically bound method call is required.
Allocation and deallocation of objects
- Where and when should objects be allocated:
- statically by the compiler
- on the run-time stack
- by the user on the heap
- Should deallocation be implicit
Dynamic and static Binding
- The question is whether all binding of messages to methods should
be dynamic.
- The alternative is to let the user specify when the binding should
be dynamic