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
