Cambridge A‑Level Computer Science 9618 – User‑defined Data Types
13.1 User‑defined Data Types
Why are user‑defined types necessary?
Built‑in primitive types (e.g., int, char, float) are limited to representing single, low‑level values. Real‑world problems often require grouping several related pieces of information and expressing higher‑level concepts. User‑defined types provide a way to model these concepts directly in code.
Abstraction: Hide implementation details and present a clear, high‑level view of data.
Encapsulation: Keep related data together, reducing the chance of mismatched values.
Reusability: Define a type once and reuse it across many modules or programs.
Readability & maintainability: Code that uses meaningful type names is easier to understand and modify.
Type safety: The compiler can detect inappropriate operations on a type, preventing many runtime errors.
Domain modelling: Directly represent entities such as Student, BankAccount, or Vector as types.
Common forms of user‑defined types
Records / structs – collections of fields of possibly different primitive types.
Enumerations (enums) – a set of named constant values.
Classes / objects – combine data (attributes) with behaviour (methods) in OOP languages.
Abstract Data Types (ADTs) – specify a set of operations without exposing the underlying representation.
Example: Modelling a Student
Consider a university system that needs to store information about each student.
Using a struct (C‑like syntax):
struct Student {
int id;
char name[50];
float gpa;
char year; // 'F' = Freshman, 'S' = Sophomore, etc.
};
Using a class (Java‑like syntax):
public class Student {
private int id;
private String name;
private double gpa;
private Year year; // enum defined elsewhere
// Constructor, getters, setters, and behaviour methods follow
}
Comparison of Built‑in vs. User‑defined Types
Aspect
Built‑in Types
User‑defined Types
Scope of representation
Single primitive value
Composite of multiple values
Abstraction level
Low
High – matches domain concepts
Reusability
Limited to the primitive itself
Can be instantiated many times across programs
Type safety
Only basic checks (e.g., overflow)
Compiler can enforce correct use of fields and operations
Maintainability
Changes require updates wherever the primitive is used
Changes confined to the type definition
Mathematical view of a user‑defined type
Formally, a user‑defined type can be seen as a Cartesian product of its component types:
\$T = T1 \times T2 \times \dots \times T_n\$
where each \$T_i\$ is the type of the \$i^{th}\$ field. For the Student example: