Records
Overview
- Record types: similar to and different from classes
- Java and Ada Examples:
- Define Java class Pair and Ada type Pair
- Client: declare and allocate variables and access fields
- Declaration and allocation of variables
- Memory allocation: value and reference semantics
- Other operations: assignment and equality
- User defined operations
- Creating ADTs
Introduction to Records
Records - The Bottom Line
- A record type is similar to a class:
- Like a class, a record is a type whose values have fields
- But a record
- Does not encapsulate methods
- Objects don't need references
- Does not deal with privacy
- Privacy is implemented using packages
Example: A Type for a Pair of Integers
- A Pair has 2 integer fields: X and Y
- We look at Java and Ada Implementations
Example: Java Class Pair
class PairClient
{
class Pair // A type for pairs
{
int x;
int y;
}
public static void main(String[] args)
{
Pair p1;
p1 = new Pair();
p1.x = 3;
p1.y = 4;
S.o.p(p1.x);
S.o.p(p1.y);
}
For now, we ignore issues of privacy with class Pair
Notice: class Pair defines a type; class PairClient holds class Pair and main
What memory is allocated in the above?
Example: Ada Record Type Pair
- Type Pair defines a type for integer pairs
procedure PairDemo is
-- Define a record type for pairs
type Pair is record
x: Integer;
y: Integer;
end record;
p1: Pair;
begin
p1.x := 3;
p1.y := 4;
put(p1.x);
put(p1.y);
end PairDemo;
Notice: Procdure PairDemo is the client and it contains the definition of type Pair
Like instance of a class, we access fields with p1.x, etc
What memory is allocated in the above?
Declaration, Allocation, Default Values, Initialization,
Aggregate Assignment
Declaration and Allocation of Variables
- Contrast the declaration and allocation of the Pair p1:
// Java
Pair p1;
p1 = new Pair();
p1.x = 3;
p1.y = 4;
-- Ada
p1: Pair;
begin
p1.x := 3;
p1.y := 4;
Consider the memory allocation in each case
Java has separate steps
- Reference variable is allocated with declaration
- Instance of class is allocated with new
Ada has a single step
- Variable declaration allocates an instance of the type
- No references!
Default Values
///////////////////////////
// Java
Pair p1;
p1 = new Pair();
S.o.p(p1.x);
S.o.p(p1.y);
---------------------------
-- Ada
p1: Pair;
begin
put(p1.x);
put(p1.y);
Java fields are initialized to 0-like values
Ada fields are NOT initialized!
Initialization
- Can we initialize the value in the declaration? Sure:
///////////////////////////
// Java
class Pair // A type for pairs
{
int x = 3;
int y = 4;
}
public static void main(...){
Pair p1;
p1 = new Pair();
S.o.p(p1.x);
S.o.p(p1.y);
---------------------------
-- Ada
type Pair is record
x: Integer := 3;
y: Integer := 4;
end record;
p1: Pair;
begin
put(p1.x);
put(p1.y);
Note: What we really need is something like constructors; we'll discuss them later.
Aggregate Assignment
- Aggregate assignment is useful for arrays, and records too:
p1: Pair := (5, 6);
begin
put(p1.x);
p1 := (7, 8);
put(p1.y);
p1 := (y => 10, x => 9);
p1 := (others => 0);
New Operations
- Soon we will see how to introduce new operations on record types
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
Operations and Reference and Value Semantics
Record Operations
- What built-in operations/actions do we have for records:
- Declaration and allocation
- Field access (ie .)
- Assignment (ie :=)
- Equality testing (ie =)
Remember Reference and Value Semantics
- From Arrays:
- Reference Semantics means ...
- Value Semantics means ...
- Complete:
- Java uses ... for ... types and ... for ... types
- Ada uses ... for ... types, unless ... are used explicitly
- Answers:
- reference semantics, reference, value semantics, primitive
- Alternate answer: reference semantics, user-defined, value semantics, primitive
- value semantics, all, pointers
- Note: Ada uses value semantics for assignment and equality tests. In some
contexts (eg parameters, for x of a loops) it uses reference semantics.
Assignment and Equality Operations
- What happens with these code fragments?
// Java
Pair p1, p2;
p1 = new Pair(1, 2); // Assume constructor
p2 = new Pair(3, 4);
p2 = p1;
if (p1 == p2) ... // True or false?
p1.x = 5;
if (p1 == p2) ... // True or false?
S.o.p(p2.x);
-- Ada
p1, p2: Pair;
begin
p1 := (1, 2);
p2 := (3, 4);
p2 := p1;
if p1 = p2 ... -- True or false?
p1.x := 5;
if p1 = p2 ... -- True or false?
put(p2.x);
Reference and Value Semantics
- As seen above:
- For records, Ada uses value semantics
- For objects, Java uses reference semantics
- Note: Ada uses value semantics for assignment and equality tests. In some
contexts (eg parameters, for x of a loops) it can use reference semantics.
References, Aliases, and Debugging
- An alias is a second name for a variable
- Aliases (ie p and q below) make debugging harder:
p = new Pair();
q = p
p.x = 99;
S.o.p(q.x);
p: Pair;
q := p;
p.x := 99;
put(q.x);
Arrays of records will show another example of
the difference between reference vs value semantics
Records as Parameters
Records as Parameters
- Can records be used as parameters: Of course
- Example: paramrecords.adb (and prettified)
- Illustrates in mode and in out mode
- The local variable of type Pair is allocated temporarily
- Let's trace the code
Swapping Pairs in Java
- Can we swap pairs in Java?
- Answer: Yes and No
- Let's try it ...
Records with functions (and Redefining Operators!)
- Function parameters and return types can be records
- Example: functionrecords.adb (and prettified)
- Illustrates records as function parameters and return type
- Illustrates redefining operators
- The local variable of type Pair is allocated temporarily
- The pair returned from the function is assigned in the client
- Let's trace the code
- Can you write plus with only one statement?
New Operations and Abstract Data Types
Record Operations
- What built-in operations/actions do we have for records:
- Declaration/allocation
- Field access (ie .)
- Assignment (ie :=)
- Equality (ie =)
Defining New Operations
- Can we define new operations? Sure:
- Example: PutPair(p: Pair);
- Example: SwapPair(p1, p2: in out Pair);
- Example: "+"(p1, p2: Pair) return Pair;
Defining Abstract Data Types (ADTs)
- How can we define ADTs?
- ADTs provide a tool for clients
- Implementing ADTs requires privacy to protect implementation
- Solution: Use packages, our next topic after records
Perspective: Terms, Composite Types
Record: The Term
- The term record is used for several related ideas
- Line of input
- Composite type (COBOL)
- Databases
- In each case, the underlying idea is several related data
values grouped together
Record and Classes: Both Define Composite Types
- Records and classes both define composite types
- Composite type have internal structure
- AKA structured types
- Record and array types
- Records and classes
- Arrays and classes both define composite (ie structured) types (ie have structure)
- Record and class types have multiple fields
- Each field has a name and a type
- Fields can be of different type
- Access fields by name which is known at compile time
- Compare with Arrays
- Arrays and Records are both composite (ie structured) types (ie have structure)
- Arrays have multiple elements
- Each field has an index and a type
- Elements are of same type
- Access element by index, may be known at compile, or not until run time
Records and Classes: Similar but Significant Differences
- Record objects do not need references
- References (ie pointers) can be used if needed
- Records do NOT contain operations (ie methods)
- Later we use packages to define new operations for record types
- Records do NOT provide privacy
- Later we use packages to provide privacy
Up Next
Up Next
- Employee List: An record containing an array, of records
- Nested records
- Comparison of records and classes