179 lines
5.4 KiB
Fortran
179 lines
5.4 KiB
Fortran
!-----------------------------------------------------------------------
|
|
!Module accuracy defines precision and some constants
|
|
!-----------------------------------------------------------------------
|
|
module accuracy_module
|
|
implicit none
|
|
integer, parameter, public :: rdp = kind(1.d0)
|
|
! constants
|
|
real(rdp), parameter :: pi=3.141592653589793238462643383279502884197_rdp
|
|
end module accuracy_module
|
|
|
|
!-----------------------------------------------------------------------
|
|
!Module typedefs_module contains abstract derived type and extended type definitions.
|
|
! Note that a reserved word "class" in Fortran is used to describe
|
|
! some polymorphic variable whose data type may vary at run time.
|
|
!-----------------------------------------------------------------------
|
|
module typedefs_module
|
|
use accuracy_module
|
|
implicit none
|
|
|
|
private ! all
|
|
public :: TPoint, TShape, TCircle, TRectangle, TSquare ! public only these defined derived types
|
|
|
|
! abstract derived type
|
|
type, abstract :: TShape
|
|
real(rdp) :: area
|
|
character(len=:),allocatable :: name
|
|
contains
|
|
! deferred method i.e. abstract method = must be overridden in extended type
|
|
procedure(calculate_area), deferred,pass :: calculate_area
|
|
end type TShape
|
|
! just declaration of the abstract method/procedure for TShape type
|
|
abstract interface
|
|
function calculate_area(this)
|
|
use accuracy_module
|
|
import TShape !imports TShape type from host scoping unit and makes it accessible here
|
|
implicit none
|
|
class(TShape) :: this
|
|
real(rdp) :: calculate_area
|
|
|
|
end function calculate_area
|
|
end interface
|
|
|
|
! auxiliary derived type
|
|
type TPoint
|
|
real(rdp) :: x,y
|
|
end type TPoint
|
|
|
|
! extended derived type
|
|
type, extends(TShape) :: TCircle
|
|
real(rdp) :: radius
|
|
real(rdp), private :: diameter
|
|
type(TPoint) :: centre
|
|
contains
|
|
procedure, pass :: calculate_area => calculate_circle_area
|
|
procedure, pass :: get_circle_diameter
|
|
final :: finalize_circle
|
|
end type TCircle
|
|
|
|
! extended derived type
|
|
type, extends(TShape) :: TRectangle
|
|
type(TPoint) :: A,B,C,D
|
|
contains
|
|
procedure, pass :: calculate_area => calculate_rectangle_area
|
|
final :: finalize_rectangle
|
|
end type TRectangle
|
|
|
|
! extended derived type
|
|
type, extends(TRectangle) :: TSquare
|
|
contains
|
|
procedure, pass :: calculate_area => calculate_square_area
|
|
final :: finalize_square
|
|
end type TSquare
|
|
|
|
contains
|
|
|
|
! finalization subroutines for each type
|
|
! They called recursively, i.e. finalize_rectangle
|
|
! will be called after finalize_square subroutine
|
|
subroutine finalize_circle(x)
|
|
type(TCircle), intent(inout) :: x
|
|
write(*,*) "Deleting TCircle object"
|
|
end subroutine finalize_circle
|
|
|
|
subroutine finalize_rectangle(x)
|
|
type(TRectangle), intent(inout) :: x
|
|
write(*,*) "Deleting also TRectangle object"
|
|
end subroutine finalize_rectangle
|
|
|
|
subroutine finalize_square(x)
|
|
type(TSquare), intent(inout) :: x
|
|
write(*,*) "Deleting TSquare object"
|
|
end subroutine finalize_square
|
|
|
|
function calculate_circle_area(this)
|
|
implicit none
|
|
class(TCircle) :: this
|
|
real(rdp) :: calculate_circle_area
|
|
this%area = pi * this%radius**2
|
|
calculate_circle_area = this%area
|
|
end function calculate_circle_area
|
|
|
|
function calculate_rectangle_area(this)
|
|
implicit none
|
|
class(TRectangle) :: this
|
|
real(rdp) :: calculate_rectangle_area
|
|
! here could be more code
|
|
this%area = 1
|
|
calculate_rectangle_area = this%area
|
|
end function calculate_rectangle_area
|
|
|
|
function calculate_square_area(this)
|
|
implicit none
|
|
class(TSquare) :: this
|
|
real(rdp) :: calculate_square_area
|
|
! here could be more code
|
|
this%area = 1
|
|
calculate_square_area = this%area
|
|
end function calculate_square_area
|
|
|
|
function get_circle_diameter(this)
|
|
implicit none
|
|
class(TCircle) :: this
|
|
real(rdp) :: get_circle_diameter
|
|
this % diameter = 2.0_rdp * this % radius
|
|
get_circle_diameter = this % diameter
|
|
end function get_circle_diameter
|
|
|
|
end module typedefs_module
|
|
|
|
!-----------------------------------------------------------------------
|
|
!Main program
|
|
!-----------------------------------------------------------------------
|
|
program rosetta_class
|
|
use accuracy_module
|
|
use typedefs_module
|
|
implicit none
|
|
|
|
! we need this subroutine in order to show the finalization
|
|
call test_types()
|
|
|
|
contains
|
|
|
|
subroutine test_types()
|
|
implicit none
|
|
! declare object of type TPoint
|
|
type(TPoint), target :: point
|
|
! declare object of type TCircle
|
|
type(TCircle),target :: circle
|
|
! declare object of type TSquare
|
|
type(TSquare),target :: square
|
|
|
|
! declare pointers
|
|
class(TPoint), pointer :: ppo
|
|
class(TCircle), pointer :: pci
|
|
class(TSquare), pointer :: psq
|
|
|
|
!constructor
|
|
point = TPoint(5.d0,5.d0)
|
|
ppo => point
|
|
write(*,*) "x=",point%x,"y=",point%y
|
|
|
|
pci => circle
|
|
|
|
pci % radius = 1
|
|
write(*,*) pci % radius
|
|
! write(*,*) pci % diameter !No,it is a PRIVATE component
|
|
write(*,*) pci % get_circle_diameter()
|
|
write(*,*) pci % calculate_area()
|
|
write(*,*) pci % area
|
|
|
|
psq => square
|
|
|
|
write(*,*) psq % area
|
|
write(*,*) psq % calculate_area()
|
|
write(*,*) psq % area
|
|
end subroutine test_types
|
|
|
|
end program rosetta_class
|