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.f90as the file name, andmodule Shape_classfor 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.