The story of the tagged record
is that in the 1990s, people had already built microprocessor architectures that supported object
emulation in caches and this set the stage for the OOP
object-oriented programming model adopted by MIT
. introduced in the late 1950s and early 1960s is becoming the focus of the software programming industry in general. And the updated 1995 version of Ada
was no exception to the popular programming languages of the time – introducing several tools to support this programming paradigm.
1995 was also the year that the Java language was officially introduced and immediately became one of the most popular programming languages with its 100%
OOP
-based design.
Tagged Record
Technically, record
in Ada
are equivalent to struct
in C
. These structures are not extensible by the derived type
and do not contain any additional identifying information other than the data fields that we define ourselves.
That is, at the time of running the software at runtime
, we will not have any specific identification information to quickly determine what type
this record
belongs to if assuming the record
have additional inheritance features. Meanwhile, identifiers like this are very important for OOP
.
And for all of the above reasons, the Ada 95
version introduced tagged record
with the aforementioned support expected features to support the OOP
model. In this article, we will temporarily only care about the scalability and inheritance of tagged record
and save the rest for a later article.
1 2 3 4 5 6 7 8 9 10 11 12 13 | package Humanity is type Person is tagged record Name : String (1 .. 12); Age : Integer; end record; type Crafter is new Person with record Level : Integer; end record; end Humanity; |
Defining a tagged record
is no different from a regular record
definition other than the additional keyword tagged
. However, as mentioned, tagged record
allows to perform inheritance operations with the same syntax as above. The with
keyword is used to merge the record
in the new definition into the record
defined in the original Person
type and create the Crafter
type.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | with Ada.Text_IO; use Ada.Text_IO; with Humanity; use Humanity; procedure Main is Someone : Crafter; begin Someone := ( Name => "Semi Dev_ " , Age => 32 , Level => 1001 ); Put_Line ("Crafter record"); Put_Line (" Name => " & Someone.Name); Put_Line (" Age => " & Integer'Image (Someone.Age)); Put_Line (" Level => " & Integer'Image (Someone.Level)); end Main; |
1 2 3 4 5 | Crafter record Name => Semi Dev_ Age => 32 Level => 1001 |
Primitive Operation
Also in this 1995 update, Ada
also introduces a concept called primitive operation
, also known as primitive
for short. This term is used to talk about the relationship between sub-program
and the data types they are designed to work around.
When sub-program
defined in the same package
as the Type data Type
are used as input parameters, those sub-program
are called primitive operation
of type Type
. Now, if we create a new data type Derived_Type
from Type
, these sub-program
will also become primitives
of Derived_Type
.
And of course, existing sub-program
will work fine with Derived_Type
without requiring us to perform data type conversion.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | package Humanity is type Person is tagged record Name : String (1 .. 12); Age : Integer; end record; procedure Put_Name (Self : in Person); procedure Put_Age (Self : in Person); -- derived - - - - - - - - - - - - - - - type Crafter is new Person with record Level : Integer; end record; procedure Put_Level (Self : in Crafter); end Humanity; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | with Ada.Text_IO; use Ada.Text_IO; package body Humanity is procedure Put_Name (Self : in Person) is begin Put_Line ("Name => " & Self.Name); end Put_Name; procedure Put_Age (Self : in Person) is begin Put_Line ("Age => " & Integer'Image (Self.Age)); end Put_Age; -- derived - - - - - - - - - - - - - - - procedure Put_Level (Self : in Crafter) is begin Put_Line ("Level => " & Integer'Image (Self.Level)); end Put_Level; end Humanity; |
Here we will move the commands that print the information of the data fields into the corresponding procedure
definitions in the package Person
. Where Put_Name
and Put_Age
are defined as primitive
of type Person
and will be applied at main.adb
with an input parameter of type Crafter
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | with Ada.Text_IO; use Ada.Text_IO; with Humanity; use Humanity; procedure Main is Someone : Crafter; begin Someone := ( Name => "Semi Dev_ " , Age => 32 , Level => 1001 ); Put_Line ("- - Crafter - - - -"); Put_Name (Someone); Put_Age (Someone); Put_Level (Someone); end Main; |
1 2 3 4 5 | - - Crafter - - - - Name => Semi Dev_ Age => 32 Level => 1001 |
The concept of primitive operation
applies not only to sub-program
that work around record
types, but to all other data types defined from unary data types such as Integer
, String
, etc..
Particularly for tagged record
, primitive operation
can also be called with the syntax using execute .
Similar to popular OOP
languages. Because of this, it is possible that in some code libraries we will be able to see examples using this syntax and in others it is recommended to use the usual visual sub-program
syntax.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | with Ada.Text_IO; use Ada.Text_IO; with Humanity; use Humanity; procedure Main is Someone : Crafter; begin Someone := ( Name => "Semi Dev_ " , Age => 32 , Level => 1001 ); Put_Line ("- - Crafter - - - -"); Someone.Put_Name; Someone.Put_Age; Someone.Put_Level; end Main; |
The choice is up to each person. For myself, I would choose to use the syntax of calling visual sub-program
in a Procedural Programming
theme language. Because the way we represent elements in the code will sometimes have the opposite effect on our own thinking tendencies. And when using a Procedural
subject language, the thinking of objectively acting on the data record
is more appropriate than the interactive way of thinking between object
and entities.
Elements borrowed from OOP
such as Inheritance
inheritance, Encapsulation
, Polymorphism
, and Abstraction
will become very useful tools. However, after all, these are just extension
features, not comparable to OOP
mainstream languages.
And in the first feature Inheritance
, the most important thing is that we have added the ability to define record
types that simulate the inheritance from real data entities. Attached are sub-program
that can also be applied to inherited types and help us reduce a lot of repetitive code.
[Procedural Programming + Ada] Lesson 10 – Type’Class & Overriding Primitives