Object orientation
| CLASS variables | |
| SELECT TYPE | |
| Polymorphic arrays | |
| Design small hierarchies |
CLASS variables
A variable declared with class instead of type can hold a value of the named type or of any type that extends it.
Such a polymorphic variable is usually allocatable, and the allocate statement chooses the concrete dynamic type at run time.
The fragment below declares a polymorphic counter and stores an extended value in it.
program demo
implicit none
use named_counters
class(counter), allocatable :: obj
allocate(named_counter :: obj)
print *, "ready"
end program demo
SELECT TYPE
A select type block tests the dynamic type of a polymorphic variable and gives a typed name to each branch.
Inside a type is branch the variable behaves like that concrete type, so child components are directly visible.
The example prints the label only when the stored value really is a named counter.
select type (obj)
type is (named_counter)
print *, obj%label
type is (counter)
print *, obj%n
class default
print *, "unknown type"
end select
Polymorphic arrays
An allocatable array of class elements can mix several child types in one container, which suits small plugin style lists.
Every element keeps its own dynamic type, and select type recovers the concrete view whenever child details matter.
The fragment allocates a two element team and calls the shared reset method on each member.
program demo
implicit none
use named_counters
class(counter), allocatable :: team(:)
allocate(counter :: team(2))
call team(1)%reset()
call team(2)%reset()
print *, size(team)
end program demo
Design small hierarchies
Keep hierarchies shallow: one abstract parent with a few concrete children covers most Fortran programs without deep trees.
Put shared state and shared methods in the parent, and let each child add only the data and overrides that it truly needs.
Prefer composition with nested types when a plain has-a relation fits better than an is-a relation, since flat code is easier to test.
program demo
implicit none
use named_counters
type(named_counter) :: job
job%n = 3
job%label = "uploads"
call job%reset()
print *, job%n, job%label
end program demo
Next: Operator overloading
Article author: Arthur Isaev