Clicky
In object-oriented languages such as C++, one can define classes that contain both data and methods which operate on that data. One can then create separate instances of the class, each with its own data. A method called from an instance of the class will work on the data held by that particular instance.
In Fortran, modules may contain data, but there is no notion of separate instances of a module. In order to obtain class-like behavior, one can combine a module, which contains the methods that operate on the class, with a derived type containing the data. There can be separate "instances" of the type in that we can allocate many variables of that type which can be passed as parameters to the methods contained in the module.
To illustrate these points consider a simple Circle class, based on an example in Akin (2003, p. 34):
module class_Circle
implicit none
private
public :: Circle, circle_area, circle_print
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type Circle
real :: radius
end type Circle
contains
function circle_area(this) result(area)
type(Circle), intent(in) :: this
real :: area
area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
type(Circle), intent(in) :: this
real :: area
area = circle_area(this) ! Call the circle_area function
print *, 'Circle: r = ', this%radius, ' area = ', area
end subroutine circle_print
end module class_Circle
program circle_test
use class_Circle
implicit none
type(Circle) :: c ! Declare a variable of type Circle.
c = Circle(1.5) ! Use the implicit constructor, radius = 1.5.
call circle_print(c) ! Call a class subroutine
end program circle_test
New features in Fortran 2003 allow us to improve upon the object-oriented approach above by using type-bound procedures which allow us to write
a = c%area
call c%print
instead of the more verbose
a = circle_area(c)
call circle_print(c)
The program above, modified to use type-bound procedures, looks like this
module class_Circle
implicit none
private
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type, public :: Circle
real :: radius
contains
procedure :: area => circle_area
procedure :: print => circle_print
end type Circle
contains
function circle_area(this) result(area)
class(Circle), intent(in) :: this
real :: area
area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
class(Circle), intent(in) :: this
real :: area
area = this%area() ! Call the type-bound function
print *, 'Circle: r = ', this%radius, ' area = ', area
end subroutine circle_print
end module class_Circle
program circle_test
use class_Circle
implicit none
type(Circle) :: c ! Declare a variable of type Circle.
c = Circle(1.5) ! Use the implicit constructor, radius = 1.5.
call c%print ! Call the type-bound subroutine
end program circle_test
Note that we have changed the dummy parameters from type(Circle)
to class(Circle)
. We can then call the class functions in an object-oriented fashion as a = c%area
and call c%print
, where the type is passed to the first argument of the functions circle_area
and circle_print
automatically. See Metcalf, Reid, and Cohen (2004, p. 279) for additional information.
Akin, E. (2003). Object-Oriented Programming Via Fortran 90/95. Cambridge University Press. (pdf)
Chin, L. S., D. J. Worth and C. Greenough (2006): Thoughts on using the Features of Fortran 95, Software Engineering Group Notes SEG-N-003 (html | pdf )
Cohen, M. (1999): Object orientation and Fortran 2002: part II, ACM SIGPLAN Fortran Forum, 18, 14–21.
Decyk, V. K., C. D. Norton, and B. K. Szymanski: Object Oriented Fortran 90 Programming
Gray, M. G. and R. M. Roberts (1997): Object-based programming in Fortran 90 (PDF, 183K). Computers in Physics, 11:355–361.
Lemmon, D. R. and J. L. Schafer. (2005). Developing Statistical Software in Fortran 95. Springer.
Markus, A. (2006): Design patterns and Fortran 90/95, ACM SIGPLAN Fortran Forum, 25, 13–29.
Metcalf, M., J. Reid, and M. Cohen (2004). Fortran 95/2003 Explained. Oxford University Press.