Define and use the five non‑composite user‑defined types required by the Cambridge AS/A‑Level syllabus, evaluate their impact on code clarity, safety and maintainability, and select the most appropriate type for a given problem (AO1–AO3).
| Unit | Content | Assessment Objective(s) |
|---|---|---|
| 13.1 | Non‑composite user‑defined types (enumerated, sub‑range, type synonyms, pointer‑type synonyms, set types) | AO1 – terminology & definitions AO2 – select appropriate type for a given problem AO3 – implement, test and evaluate a solution |
Non‑composite types are atomic: they are not built from other types. They differ from composite types (records, arrays, ADTs) which combine several values. The five non‑composite types listed in the syllabus are:
| Aspect | Non‑composite | Composite |
|---|---|---|
| Construction | Defined from a single existing ordinal type or from a pointer | Built from two or more component types (e.g., record, array) |
| Memory layout | Single value (or a single pointer) | Multiple contiguous or linked values |
| Typical use | Represent a limited set of concepts, enforce a numeric range, give a domain‑specific name, or create a simple pointer alias | Group related data (e.g., a student record) or store collections (e.g., an array of marks) |
An enumerated type defines a finite, named set of possible values. Each value is an enumeration constant. Internally the compiler stores them as integers (ordinal values), but the program works only with the symbolic names.
typeColour = (Red, Green, Blue);
enum Colour { RED, GREEN, BLUE }c := Red; (Pascal) or Colour c = Colour.RED; (Java)if c = Blue then … or if (c == Colour.BLUE) …next := Succ(c); (Pascal) or Colour[] v = Colour.values(); Colour next = v[(c.ordinal()+1)%v.length]; (Java)for c := Low(Colour) to High(Colour) do … (Pascal) or for (Colour c : Colour.values()) … (Java)Most compilers assign the first constant the ordinal value 0, the second 1, etc., but the exact numeric values are not guaranteed by the language standard. Therefore:
Red = 0 in program logic.Think‑Pair‑Share: Design an enum Day for the seven days of the week. In pairs decide which days are “weekend” and write a short method that returns true for weekend days. Discuss why an enum is a better choice than a set of integer constants.
Write a JUnit test that passes each enum constant to the method created above and asserts the correct Boolean result.
A subrange type restricts an existing ordinal type (integer, char, or enumerated) to a contiguous interval of values.
typeScore = 0..100; { integer subrange }
GradeLetter = 'A'..'F'; { character subrange }
Java has no built‑in subrange type. The same effect is achieved with a small wrapper class that validates the value in the constructor.
final class Score {private final int value;
public Score(int v) {
if (v < 0 || v > 100)
throw new IllegalArgumentException("Score out of range");
this.value = v;
}
public int get() { return value; }
}
s := 85; (Pascal) – range‑checked at run‑time.if s > 70 then …constBadScore : Score = 101; { compile‑time error: value out of range }
Given the problem “store a patient’s temperature in Celsius, which will never be below –30 or above 45”, decide whether a subrange or a type synonym is more appropriate and justify your choice.
Create test cases that attempt to construct a Score with values –1, 0, 100 and 101. Verify that only –1 and 101 throw an exception.
A type synonym creates a new name for an existing type. It does not create a distinct type; the two names are interchangeable.
typeStudentID = integer;
Temperature = real;
Java has no direct typedef. The intent is conveyed by:
class StudentID { private final int value; … }) when a distinct type is required.Price = real;).Because the synonym is not a separate type, the compiler will not prevent mixing it with its base type. Logical errors must be caught by the programmer (e.g., adding a StudentID to a plain integer that represents a score).
Write a short paragraph explaining why type Money = real; is a better choice than using real directly in a banking application.
A pointer‑type synonym creates a new name for a pointer to an existing type. It is useful when the same pointer type is used in several places (e.g., linked‑list nodes).
typeNodePtr = ^Node; { pointer‑type synonym }
Node = record
data : integer;
next : NodePtr;
end;
Java references are implicit; a synonym is expressed by a class name. For linked lists we typically write:
class Node {int data;
Node next; // “NodePtr” is implicit
}
Using a synonym makes the intention explicit (e.g., “this variable holds a pointer to a node”) and allows a single point of change if the underlying structure is altered.
Confusing a pointer‑type synonym with a new record type – the synonym does not introduce a new structure, only a new name for the same pointer.
A set type defines a collection of values taken from an ordinal base type. The set itself is a non‑composite type because it is stored as a bit‑vector rather than as a collection of separate objects.
typeDay = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
DaySet = set of Day;
Java uses EnumSet which is a specialised, efficient implementation of a set of enum constants.
enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }EnumSet<Day> weekend = EnumSet.of(Day.SAT, Day.SUN);
if Mon in WorkDays then … (Pascal) or if (workDays.contains(Day.MON)) … (Java)AllDays := WorkDays + Weekend; or EnumSet<Day> all = EnumSet.copyOf(workDays); all.addAll(weekend);for d := Low(Day) to High(Day) do if d in MySet then …Model a school timetable where each class can be scheduled on any subset of the days Monday–Friday. Choose between a set type and an array of Boolean flags, and justify your choice.
Colour, Score, StudentID).program NonCompositeDemo;{---------------------------------------------------------------}
{ Demonstrates enumerated, subrange, type synonym, }
{ pointer‑type synonym and set types. }
{---------------------------------------------------------------}
type
Colour = (Red, Green, Blue); { enumerated }
Score = 0..100; { subrange }
StudentID = integer; { type synonym }
{ linked‑list node }
NodePtr = ^Node; { pointer‑type synonym }
Node = record
id : StudentID;
mark : Score;
next : NodePtr;
end;
Day = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
DaySet = set of Day; { set type }
var
c : Colour;
s : Score;
id : StudentID;
head: NodePtr;
workDays, weekend, allDays: DaySet;
function CalculateGrade(m : Score) : (A, B, C, D, F);
begin
case m of
90..100: CalculateGrade := A;
80..89 : CalculateGrade := B;
70..79 : CalculateGrade := C;
60..69 : CalculateGrade := D;
else CalculateGrade := F;
end;
end;
procedure AddNode(var list: NodePtr; nid: StudentID; nscore: Score);
var
newNode: NodePtr;
begin
new(newNode);
newNode^.id := nid;
newNode^.mark := nscore;
newNode^.next := list;
list := newNode;
end;
begin
{--- Enumerated & Subrange ---}
c := Red;
s := 78; { range‑checked at run‑time }
id := 12345;
writeln('Student ', id, ' scored ', s, ' (', Colour(c), ')');
{--- Pointer‑type synonym ---}
head := nil;
AddNode(head, 10001, 85);
AddNode(head, 10002, 92);
{--- Set type ---}
workDays := [Mon, Tue, Wed, Thu, Fri];
weekend := [Sat, Sun];
allDays := workDays + weekend; { union }
writeln('All days count: ', Ord(High(Day)) - Ord(Low(Day)) + 1);
end.
enum Colour { RED, GREEN, BLUE }enum Grade { A, B, C, D, F }
enum Day { MON, TUE, WED, THU, FRI, SAT, SUN }
final class Score {
private final int value;
public Score(int v) {
if (v < 0 || v > 100) throw new IllegalArgumentException("Score out of range");
this.value = v;
}
public int get() { return value; }
}
final class StudentID {
private final int value;
public StudentID(int v) { this.value = v; }
public int get() { return value; }
}
/* linked‑list node – pointer‑type synonym is implicit */
class Node {
StudentID id;
Score mark;
Node next;
Node(StudentID i, Score m, Node n) { id = i; mark = m; next = n; }
}
public class NonCompositeDemo {
public static Grade calculateGrade(Score s) {
int v = s.get();
if (v >= 90) return Grade.A;
else if (v >= 80) return Grade.B;
else if (v >= 70) return Grade.C;
else if (v >= 60) return Grade.D;
else return Grade.F;
}
public static void main(String[] args) {
Colour c = Colour.RED;
Score s = new Score(78);
StudentID id = new StudentID(12345);
System.out.println("Student " + id.get() + " scored " + s.get() + " (" + c + ")");
/* linked list */
Node head = null;
head = new Node(new StudentID(10001), new Score(85), head);
head = new Node(new StudentID(10002), new Score(92), head);
/* set type using EnumSet */
java.util.EnumSet workDays = java.util.EnumSet.range(Day.MON, Day.FRI);
java.util.EnumSet weekend = java.util.EnumSet.of(Day.SAT, Day.SUN);
java.util.EnumSet allDays = java.util.EnumSet.copyOf(workDays);
allDays.addAll(weekend);
System.out.println("All days = " + allDays);
}
}
| Type | Purpose | Pascal syntax | Java analogue | Typical values |
|---|---|---|---|---|
| Enumerated | Fixed set of named constants | type Colour = (Red, Green, Blue); | enum Colour { RED, GREEN, BLUE } | Red, Green, Blue |
| Subrange | Restrict an ordinal type to a contiguous interval | type Score = 0..100; | Wrapper class with range check | 0 … 100 |
| Type synonym | Give a domain‑specific name to an existing type | type StudentID = integer; | Comment or wrapper class | integer |
| Pointer‑type synonym | New name for a pointer to an existing type | type NodePtr = ^Node; | Implicit reference (class name) in Java | NodePtr = ^Node |
| Set type | Compact collection of values from an ordinal base type | type DaySet = set of Day; | EnumSet<Day> | {Mon, Tue, …, Sun} |
A) An enumerated type can be compared directly with an integer.
B) A subrange type can only be defined for real values.
C) A type synonym creates a new, distinct representation.
D) All of the above.
Answer: None – enumerated types compare with their constants, subranges apply to ordinal types, and synonyms do not create a new representation.
Age that allows values from 0 to 120.Age.Day for the seven days of the week. Write a procedure printDayType that prints “Weekend” for Saturday and Sunday, otherwise “Weekday”. Provide a JUnit test case for each branch.Age (0..120). Write a function isLegalVoter that returns true if the age is ≥ 18. Supply two test cases (one legal, one illegal) and state the expected outcomes.type Money = real; and type Money = 0..1000; in terms of allowed values, precision and program safety. Suggest a scenario where each would be preferable.CountNodes that returns the number of nodes in the list. Show a Java method that performs the same task on the Node class.Weekend of type DaySet. Write a Pascal expression that tests whether a variable d : Day is a weekend day, and the equivalent Java expression using EnumSet.| Item | Present? |
|---|---|
| Definition of all five non‑composite types | ✓ |
| Pascal syntax & Java equivalents | ✓ |
| Typical operations (assign, compare, iterate, set ops) | ✓ |
| AO mapping (AO1‑AO3) | ✓ |
| Design activity (AO2) for each type | ✓ |
| Testing activity (AO3) for each type | ✓ |
| Common misconceptions (ordinal values, range checking, synonym mixing) | ✓ |
| Comparison with composite types | ✓ |
| Explicit compile‑time range‑error example | ✓ |
| Discussion of ordinal vs. non‑ordinal representations | ✓ |
| Quick‑check quiz & practice questions | ✓ |
Students should rewrite the full Pascal example in Java (or Python/Visual Basic) to solidify translation of non‑composite types across languages. Suggested tasks:
Grade enum and calculateGrade method in Java.Score class that enforces the 0‑100 range and write JUnit tests for the boundary values 0, 100 and 101.StudentID and discuss how it differs from a simple type synonym.EnumSet<Day> to model working days and weekend days, then write a method that returns true if a given Day is a weekend.Completing these activities will give students practice in:
Your generous donation helps us continue providing free Cambridge IGCSE & A-Level resources, past papers, syllabus notes, revision questions, and high-quality online tutoring to students across Kenya.