Nested Records and Nested Composite Types
Nested Records and Nested Composite Types
Nested Composite Type: Class and Record Type Line
Nested Composite Type
- Primitive type:
- Has no internal structure
- A variable holds a single value
- Examples: Integer, float, character
- Composite Type:
- Has internal structure
- Examples: arrays and records (and classes)
- Nested Composite Type:
- Some or all fields are other composite types
Example: Class Line
- A Line is defined by two points
- A type for a line contains a field for each point
- In Java, we implement a line with two pair fields
- In Ada, we implement a line with nested records
Example: Class Line
- Let's implement type Line in Java
- A line segment is modeled using a two Pairs
- Each line has has a start Pair and an end Pair
class Pair{
int x;
int y;
Pair(int x, int y){
this.x = x; this.y = y;
}
...
}
class Line{
Pair start;
Pair end;
...
}
...
// CLIENT
Line myLine;
myLine = new Line();
myLine.start = new Pair(1, 2):
myLine.end = new Pair(3, 4):
S.o.p(myLine.start.x);
S.o.p(myLine.end.x);
Type Line in Ada
- Let's implement type Line with nested records
type Pair is record
x: Integer;
y: Integer;
end record;
type Line is record
start: Pair;
end: Pair;
end record;
myLine: Line;
begin
myLine.start.x := 1;
myLine.start.y := 2;
myLine.end := (3, 4);
put(myLine.start.x);
put(myLine.end.x);
Composite Objects: Reference and Value Semantics
Composite Objects: Reference and Value Semantics
-
In a language that has reference semantics (eg in java)
the fields of a composite object are actually references
to other objects.
- Notice the difference between what is in a Line object in Java
and Ada
- Java: Two pointers
- Ada: Four integers
- Notation for access is identical, but memory allocation and
actions required for data access are significantly different
- In java, composite objects always have reference
semantics (ie have fields that are pointers).
- In Ada and C++, composite objects can have either
reference or value semantics (ie the fields can be either
values or pointers).
Aggregation vs Composition
Aggregation vs Composition
- In Object Modeling (eg UML) we have two ways
of making one type
part of another
- Aggregation: the nested object has a separate
existance from the composite
- Composition: the nested object cannot be separated from the composite
- Example:
- University:
- Deparment made up of Faculty members - aggregation
- University made up of Departments - composition
- Department is an aggregation of faculty
- Even if the university and departments are destroyed, the faculty still exist
- University is a composition of department
- If the university no longer exists, then neither do the departments
- What is a natural way of implementing ...
- How do we draw in UML ...
- Composition - University has filled diamond, other end is Department
- Aggregation - Department has unfilled diamond, other end is Faculty
- Composition - with nested records
- Aggregation - with references
Array of Lines and List of Lines
Example: An Array of Lines
- What does an array of lines look like:
- Java:
// Declaration and allocation of the array
Line[] myArray;
myArray = new Line[3];
// Initialize
...
- Ada:
-- Declaration of the array type
type LineArray is array(1..3) of Line;
-- Declaration and allocation of the array
myArray: LineArray;
-- Initialize
...
- Consider both syntax and memory allocation of myArray
- Consider both syntax and actions of accessing myArray
Record of Array of Records: LineList
- What would a data structure look like for a list of lines
- The list would contain the following:
- Array of lines
- Count of the number of valid lines in the array
- An almost complete solution: linelist.adb
(and prettified)
- Contains routines for reading a list of lines from input and for
creating a list of random lines.
Types for Record Fields
Legal Types for Record Fields
- Requirements for types of record fields:
- Size must be known at compile time:
- Must use a named type:
- Example - Will not compile:
type Unc_Array_T is array(Natural range <>) of Integer;
type NotLegal is record
a: array(1 .. 10) of Natural; -- Not a named type
b: Unc_Array_T; -- Size not known
c: String; -- Size not known
end record;
Example - Will compile:
type MyArray is array(1 .. 10) of Natural;
type Unc_Array_T is array(Natural range <>) of Integer;
type NotLegal is record
a: MyArray; -- Named type
b: Unc_Array_T(1..5); -- Unconstrained type with range constraint
c: String(1 .. 10); -- String is an unconstrained type
end record;
Getting Around this Restriction
- Possible solutions:
- Use unbounded string
- Use unconstrained types with explicit constraints (as above)
- Use parameters and declare blocks
- Use a discriminated record
- Later we will use pointers (whose size is known)
- Solution 1 - Unbounded string:
with ada.strings.unbounded; use ada.strings.unbounded;
with ada.text_io.unbounded_io; use ada.text_io.unbounded_io;
procedure tryrec1 is
type myRecord is
s1: Unbounded_String;
s2: Unbounded_String;
end record;
m: myRecord;
begin
m.s1 := get_line;
get_line(m.s2);
Solution 2 - Parameter and declare block
procedure tryrec2 is
procedure foo(N: natural) is
type r is record
s: String(1 .. n);
end record;
begin
null;
end foo;
i: natural;
begin
foo(3);
get(i);
declare
type r is record
s: String(1 .. i);
end record;
ar: r := (s => (others => ' '));
begin
put(ar.s(1));
end; -- declare
end tryrec2;
Solution 3 - Discriminated record (ie type definition includes a size parameter)
procedure tryrec3 is
type myRecord(size1: Natural; size2: Natural := 10) is
s1: String(1 .. size1);
s2: String(1 .. size2);
end record;
-- Size1 and size2 are discriminants (ie parameters)
-- for creating variables of this type
m1: myRecord(11, 22);
-- Create strings of size 11 and 22
m2: myRecord(33);
-- Create strings of size 33 and 10, the default
begin
put(m1.s1'last); -- 11
put(m1.s2'last); -- 22
put(m2.s1'last); -- 33
put(m2.s2'last); -- 10
Unique Word List and a Word Type
Class Project: A List of Unique Words and their Frequencies
- Input: list of words, one word per line, each word is shorter than 80 characters
- Output: Print list of unique words and their frequecies
- Constraint: main is two lines:
l: WhatTypeIsThis;
begin
getWords(l);
putWordsAndFreqs(l);
end words;
Assume some maximum possible number of input words and unique words.
Hint: Use get_line(s, len);
which reads a complete
line into string s and puts the number of characters read into len
What structure would prove useful?
Partial Roadmap:
- Design types (draw pictures)
- Read and write all words, ignoring test for uniqueness
- Enter all words into array and print the array
Solution: dis.adb
and
prettified
A Type for Words
- Define a new type Word: to be a String and a length
- A Word has a String and a length
- How would we define the data type
- What operations for words might we want?
- e...
- p...
- pl...
- ne...
- to...
- le...
- trysimpleword.adb (prettified)
- Last question: Wouldn't we want to encapsulate the word type?
- Answer: Yes, package are our next topic