Types

Writing applications in Object Pascal starts from defining custom types. Only the simplest programs can get away with just using built-in types. Once you have defined your types, you start writing code and implement algorithms that operate on your types or data structures. The more carefully your types are designed, the more clean and readable your code will be.

Object Pascal comes with many different built-in types that you can use to define your own custom types. With experience, it will become more obvious how to model your problem domain. If you write an app to manage grades in a school, you would probably want to model the abstraction of a school grade. Should it be a constant, an enumerated type, a record, or a class?

Every country and education level has different grading schemes. As an example, let's consider the grading system that was used in my primary school in Poland. There were only four grades: very good (5), good (4), sufficient (3), and insufficient (2). At first, we could be tempted to use numbers as grades in our code. Refer to the following code snippet:

var 
  grade: integer; 

That is not an optimal design. What if our application assigns a value by mistake to a grade variable that is negative or too big?

In this particular case, it would be better to define a school grade as an enumerated type. This will make our code less error-prone and much more readable. There are two different ways of defining an enumerated type. Traditionally, we would define the TSchoolGrade enumeration as follows:

type 
  TSchoolGrade = (sgVeryGood, sgGood, sgSufficient, sgInsufficient); 

Somewhere in our code, we have a variable of the TSchoolGrade type, which can only hold one of the four possible grades defined by this type. Now our code is better. The sg prefix helps us remember that the sgGood identifier, for example, is, in fact, one of the possible school grade values. The other possibility is to use the enumerated values in the fully qualified form. With the SCOPEDENUMS ON/OFF compiler directive, we can enforce using a fully qualified form of an enumeration, as shown in the following code snippet:

{$SCOPEDENUMS ON} 
type 
  TSchoolGrade = (VeryGood, Good, Sufficient, Insufficient); 
 
procedure DoWork; 
var sg: TSchoolGrade; 
begin 
  sg := VeryGood; // error, needs scope 
  sg := TSchoolGrade.VeryGood; // correct syntax 
  // ... 

Now, we do not really need the sg prefix anymore. It is up to your personal taste as to which form of defining enumerated types to use. The first one is more compact. The second one may be more readable.