OOP - Fortran
Table of Contents
1. Introduction
The basic idea is that "object oriented programming" in Fortran amounts to:
- Class approximated by "derived types" in Fortran
- Instance is a concrete object allocated in memory
- Component or Field is a "slot" in the class
- Method is a subroutine or function associated with a field
1.1. Example
Here's an example of a class, namely Shape
:
type Shape integer :: color logical :: filled integer :: x integer :: y end type Shape
Caution: fields are public by default in Fortran. To make fields private, we could do the following:
type Shape integer, private :: color logical, protected :: filled integer :: x integer :: y end type Shape
1.2. Suggestions
- If writing a class (like
Shape
), place the code in a module (likeshape_mod
) which is inside its own file (namedshape_mod.f90
)- I've come to like writing
Shape_class.f90
as the file name, andmodule Shape_class
for the module name (although I'm certain, I will change my mind soon enough)
- I've come to like writing
- Consider using PascalCase for class names
2. Constructors
There are a few default constructors provided:
Shape(0, .false., 3, 7) ! Initialize with positional arguments Shape(x = 5, color = 33, y = 1, filled = .false.) ! keyword arguments
2.1. Custom Constructor
We can override the default constructor to have a smart constructor, using Fortran's interfaces.
pure type(Shape) function new_shape(x, y, color) result(res) integer, intent(in) :: x, y, color res%color = color res%filled = .true. res%x = x res%y = y end function new_shape
We could even do some validation on the inputs provided. But now comes
the fancy part, where we use an interface
to bind Shape
's
constructor to new_shape(x, y, color)
:
interface Shape module procedure :: new_shape end interface Shape
3. Binding Methods to a Class
We just need to add a contains
to our type declaration, and specify
we're passing self
along as a parameter:
module Shape_class implicit none type Shape integer :: color logical :: filled integer :: x integer :: y contains procedure, pass(self) :: area end type Shape contains pure integer function area(self) type(Shape), intent(in) :: self area = self%x * self%y end function area end module Shape_class
CAUTION: when doing polymorphism, instead of writing type(Shape)
,
you need to write class(Shape)
, so that any children of Shape
can
use area
.
4. References
- Milan Curcic, Modern Fortran, chapter 8.