Introduction
Generics and collections are powerful features in Delphi/Object Pascal that allow you to create flexible and reusable code. Generics enable you to define classes, procedures, and functions with a placeholder for the data type, which can be specified when the generic is instantiated. Collections, on the other hand, are data structures that store and manage groups of objects.
In this section, we will cover:
- Understanding Generics
- Using Generic Classes and Methods
- Common Collection Types
- Practical Examples
- Exercises
Understanding Generics
Generics allow you to write code that can operate on different data types without being rewritten for each type. This is achieved by defining a generic type parameter.
Key Concepts
- Type Parameter: A placeholder for a data type that is specified when the generic is instantiated.
- Generic Class: A class that uses type parameters.
- Generic Method: A method that uses type parameters.
Syntax
Here is the basic syntax for defining a generic class:
type TGenericClass<T> = class private FValue: T; public constructor Create(AValue: T); function GetValue: T; procedure SetValue(AValue: T); end;
In this example, T
is a type parameter that will be replaced with a specific type when the class is instantiated.
Using Generic Classes and Methods
Example: Generic Class
Let's create a simple generic class to store and retrieve a value:
type TBox<T> = class private FValue: T; public constructor Create(AValue: T); function GetValue: T; procedure SetValue(AValue: T); end; constructor TBox<T>.Create(AValue: T); begin FValue := AValue; end; function TBox<T>.GetValue: T; begin Result := FValue; end; procedure TBox<T>.SetValue(AValue: T); begin FValue := AValue; end;
Instantiating a Generic Class
You can instantiate the generic class with different types:
var IntBox: TBox<Integer>; StrBox: TBox<String>; begin IntBox := TBox<Integer>.Create(123); StrBox := TBox<String>.Create('Hello, Generics'); Writeln(IntBox.GetValue); // Output: 123 Writeln(StrBox.GetValue); // Output: Hello, Generics end;
Example: Generic Method
You can also define generic methods within a class:
type TUtils = class public class function Swap<T>(var A, B: T): Boolean; end; class function TUtils.Swap<T>(var A, B: T): Boolean; var Temp: T; begin Temp := A; A := B; B := Temp; Result := True; end;
Using a Generic Method
var X, Y: Integer; begin X := 10; Y := 20; TUtils.Swap<Integer>(X, Y); Writeln(X); // Output: 20 Writeln(Y); // Output: 10 end;
Common Collection Types
Delphi provides several generic collection types in the Generics.Collections
unit:
TList<T>
: A dynamic array of items.TDictionary<TKey, TValue>
: A collection of key-value pairs.TQueue<T>
: A first-in, first-out (FIFO) collection.TStack<T>
: A last-in, first-out (LIFO) collection.
Example: TList
uses System.Generics.Collections; var IntList: TList<Integer>; begin IntList := TList<Integer>.Create; try IntList.Add(1); IntList.Add(2); IntList.Add(3); Writeln(IntList[0]); // Output: 1 Writeln(IntList[1]); // Output: 2 Writeln(IntList[2]); // Output: 3 finally IntList.Free; end; end;
Example: TDictionary<TKey, TValue>
uses System.Generics.Collections; var Dict: TDictionary<String, Integer>; begin Dict := TDictionary<String, Integer>.Create; try Dict.Add('One', 1); Dict.Add('Two', 2); Dict.Add('Three', 3); Writeln(Dict['One']); // Output: 1 Writeln(Dict['Two']); // Output: 2 Writeln(Dict['Three']); // Output: 3 finally Dict.Free; end; end;
Practical Examples
Example: Using TQueue
uses System.Generics.Collections; var Queue: TQueue<String>; begin Queue := TQueue<String>.Create; try Queue.Enqueue('First'); Queue.Enqueue('Second'); Queue.Enqueue('Third'); Writeln(Queue.Dequeue); // Output: First Writeln(Queue.Dequeue); // Output: Second Writeln(Queue.Dequeue); // Output: Third finally Queue.Free; end; end;
Example: Using TStack
uses System.Generics.Collections; var Stack: TStack<String>; begin Stack := TStack<String>.Create; try Stack.Push('First'); Stack.Push('Second'); Stack.Push('Third'); Writeln(Stack.Pop); // Output: Third Writeln(Stack.Pop); // Output: Second Writeln(Stack.Pop); // Output: First finally Stack.Free; end; end;
Exercises
Exercise 1: Create a Generic Pair Class
Create a generic class TPair<T1, T2>
that stores a pair of values. Implement methods to get and set the values.
Solution:
type TPair<T1, T2> = class private FFirst: T1; FSecond: T2; public constructor Create(AFirst: T1; ASecond: T2); function GetFirst: T1; function GetSecond: T2; procedure SetFirst(AFirst: T1); procedure SetSecond(ASecond: T2); end; constructor TPair<T1, T2>.Create(AFirst: T1; ASecond: T2); begin FFirst := AFirst; FSecond := ASecond; end; function TPair<T1, T2>.GetFirst: T1; begin Result := FFirst; end; function TPair<T1, T2>.GetSecond: T2; begin Result := FSecond; end; procedure TPair<T1, T2>.SetFirst(AFirst: T1); begin FFirst := AFirst; end; procedure TPair<T1, T2>.SetSecond(ASecond: T2); begin FSecond := ASecond; end;
Exercise 2: Use TDictionary to Count Word Frequencies
Write a program that reads a list of words and uses TDictionary<String, Integer>
to count the frequency of each word.
Solution:
uses System.Generics.Collections, System.SysUtils; var Words: TArray<String>; WordCount: TDictionary<String, Integer>; Word: String; begin Words := ['apple', 'banana', 'apple', 'orange', 'banana', 'apple']; WordCount := TDictionary<String, Integer>.Create; try for Word in Words do begin if WordCount.ContainsKey(Word) then WordCount[Word] := WordCount[Word] + 1 else WordCount.Add(Word, 1); end; for Word in WordCount.Keys do Writeln(Word, ': ', WordCount[Word]); finally WordCount.Free; end; end;
Conclusion
In this section, we explored the concept of generics and collections in Delphi/Object Pascal. We learned how to define and use generic classes and methods, and we examined some common collection types provided by Delphi. By understanding and utilizing these features, you can write more flexible, reusable, and efficient code.
Next, we will delve into multithreading and parallel programming, where we will learn how to execute multiple tasks concurrently to improve the performance of our applications.
Delphi/Object Pascal Programming Course
Module 1: Introduction to Delphi/Object Pascal
- Introduction to Delphi and Object Pascal
- Setting Up the Development Environment
- First Delphi Application
- Basic Syntax and Structure
- Variables and Data Types
Module 2: Control Structures and Procedures
- Conditional Statements
- Loops and Iteration
- Procedures and Functions
- Scope and Lifetime of Variables
- Error Handling and Debugging
Module 3: Working with Data
Module 4: Object-Oriented Programming
- Introduction to OOP
- Classes and Objects
- Inheritance and Polymorphism
- Interfaces and Abstract Classes
- Exception Handling in OOP
Module 5: Advanced Delphi Features
- Generics and Collections
- Multithreading and Parallel Programming
- Component-Based Development
- Delphi Runtime Library (RTL)
- Advanced Debugging Techniques
Module 6: GUI Development with VCL and FMX
- Introduction to VCL
- Creating Forms and Controls
- Event-Driven Programming
- Introduction to FireMonkey (FMX)
- Cross-Platform Development with FMX
Module 7: Web and Mobile Development
- Web Development with Delphi
- RESTful Services
- Mobile Development with Delphi
- Deploying Mobile Applications
- Integrating with Web Services
Module 8: Best Practices and Design Patterns
- Code Organization and Documentation
- Design Patterns in Delphi
- Refactoring Techniques
- Unit Testing and Test-Driven Development
- Performance Optimization