module class_Circle
implicit none
private
real :: pi = 3.1415926535897931d0 ! Class-wide private constant
type, public :: Circle
real :: radius
contains
procedure, public, pass :: area => circle_area
procedure, public, pass :: 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
The compiler output is:
PGF90-S-0142-area is not a member of this RECORD (testit.f95: 22)
PGF90-S-0075-Subscript, substring, or argument illegal in this context for area (testit.f95: 22)
0 inform, 0 warnings, 2 severes, 0 fatal for circle_print
PGF90-S-0155-Missing element in structure constructor- type circle (testit.f95: 33)
PGF90-S-0142-print is not a member of this RECORD (testit.f95: 34)
0 inform, 0 warnings, 2 severes, 0 fatal for circle_test
There are a couple of things I see. First, you aren’t initializing c correctly. To set c’s radius you just need to do:
c%radius = 1.5
If you want to make this setting a call, or you want to keep radius private, then you’d need a circle_initialize subroutine that has a this%radius = radius sort of line in it and you call with call c%initialize(1.5) or some such.
Beyond that, I think it might be an issue of using names multiple times (lots of area’s) or the private/public bits. I slightly rewrote this to look like some OOF I’ve done (which is based on the style in Chapman) and came up with:
module class_Circle
implicit none
real, private :: pi = 3.1415926535897931d0 ! Class-wide private constant
type, public :: Circle
real :: radius
contains
procedure, public, pass :: area => circle_area
procedure, public, pass :: print => circle_print
end type Circle
private :: circle_area, circle_print
contains
real function circle_area(this)
class(Circle) :: this
circle_area = pi * this%radius**2
end function circle_area
subroutine circle_print(this)
class(Circle) :: this
print *, 'Circle: r = ', this%radius, ' area = ', this%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%radius=1.5 ! Use the implicit constructor, radius = 1.5.
call c%print() ! Call the type-bound subroutine
end program circle_test
I decided to remove any confusion with lots of area’s by just returning circle_area in the function. And, also, added () after function/subroutine calls. I’ve always done this. I think it’s necessary, but the c%print doesn’t seem to need them. this%area does. Finally, I’m not sure you need intent(in) with the class calls. I’ve never seen those.
I’m not sure this is elegant, but it seems to work. Maybe some real OO gurus can pipe up with better OO code than this.
Thanks much for taking the time to rework my example.
Based on my reading of Fortran 95/2003 Explained (Metcalf,Reid, Cohen),
my original example should have worked, but your modifications allow me to move forward.
Disturbingly, trying to initialize a circle instance as follows:
The code is fine. We’re in the process of adding F2003 support to the compilers and 10.9 is close but not all the way there. Your code will compile with the 11.0 compilers due out in a few weeks.