UPDATE: Modified the code correcting the mistake, if anyone is interested in it as an example
I'm trying to get the hang of OOP in Fortran, but got some problems. Any help will be highly appreciated:
I want to store pointers to objects extended by an abstract class in an array and then call one of the abstract subroutines for these objects. However I get an compilation error where I'm trying to call the subroutine:
src/Body_set.f90(74): error #6553: A function reference is invoking a subroutine subprogram. [GET_MASS]
write(*,*) "Body ", i, " - mass: ", b%get_mass()
----------------------------------------------^
src/Body_set.f90(74): error #6402: prPromoteSym : Illegal KIND & CLASS mix [GET_MASS]
write(*,*) "Body ", i, " - mass: ", b%get_mass()
----------------------------------------------^
src/Body_set.f90(74): error #7021: Name invalid in this context [GET_MASS]
write(*,*) "Body ", i, " - mass: ", b%get_mass()
----------------------------------------------^
compilation aborted for src/Body_set.f90 (code 1)
I've got a abstract class in Body.f90 with two deferred procedures:
module Body_module
implicit none
private
type, public, abstract :: Body
private
contains
procedure(get_mass), deferred :: get_mass
procedure(set_mass), deferred :: set_mass
end type Body
abstract interface
function get_mass(self) result(m)
import Body
class(Body), intent(in) :: self
double precision m
end function
subroutine set_mass(self, m)
import Body
class(Body) :: self
double precision m
end subroutine
end interface
end module Body_module
Then I've got a simple class with an pointer array that should keep different objects that extends the abstract Body
class, Body_set.f90 (I've included all used subroutines, but the important one is at the bottom):
module Body_set_module
use Body_module
implicit none
private
type, public :: Body_container
class(Body), pointer :: obj
end type Body_container
type, public :: Body_set
private
integer :: num_bodies
type(Body_container), allocatable, dimension(:) :: bodies
contains
procedure :: set_body
procedure :: get_body
procedure :: get_num_bodies
procedure :: print_summary
final :: destructor
end type Body_set
interface Body_set
procedure constructor
end interface Body_set
contains
!Object contructor
function constructor(num_bodies) result(self)
class(body_set),pointer :: self
integer :: num_bodies
allocate(self)
self%num_bodies = num_bodies
allocate(self%bodies(num_bodies))
end function constructor
!Returns number of bodies stored
function get_num_bodies(self) result(num_bodies)
class(Body_set), intent(in) :: self
integer :: num_bodies
num_bodies = self%num_bodies
end function get_num_bodies
!Set element `i` to point to `new_body`
subroutine set_body(self, new_body, i)
class(body_set), intent(inout) :: self
class(Body), target, intent(in) :: new_body
integer, intent(in) :: i
self%bodies(i)%obj => new_body
end subroutine set_body
!Return pointer to body `i`
function get_body(self, i) result(the_body)
class(Body_set), intent(in) :: self
integer, intent(in) :: i
class(Body), pointer :: the_body
the_body => self%bodies(i)%obj
end function get_body
Important part of Body_set.f90:
!Print a summary of all bodies
subroutine print_summary(self)
class(body_set), intent(in) :: self
integer :: i
class(Body), pointer :: b
write(*,*) "Summary of ", self%num_bodies, " bodies:"
do i=1,self%get_num_bodies()
b => self%get_body(i)
write(*,*) "Body ", i, " - mass: ", b%get_mass()
end do
end subroutine print_summary
subroutine destructor(self)
type(body_set), intent(in) :: self
end subroutine
end module Body_set_module
C++ and Fortran 90 are compared as object-oriented languages for use in scientific computing. C++ is a full-featured, object-oriented language that provides support for inheritance and polymorphism.
It is a nonempty sequence of data and occupies a group of contiguous storage locations. An array has a name, a set of elements, and a type. An array name is a symbolic name for the whole sequence of data. An array element is one member of the sequence of data.
Object Oriented Programming (OOP) is a programming method that represents concepts as “objects” that contain data and procedures which operate on the data. Objects offer an effective and structured way to organize computer programs. In fortran, modules are one important component of (OOP).
Classes in Fortran are just plain type structures that contain attributes and methods. The functions and subroutines of a class have to be listed under contains . The visibility of each method can be set to either public or private .
The error is simple and very clear. You are calling a subroutine as a function. You can call a subroutine only using call
. You probably wanted a function in the defining interface for get_mass
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With