我对 Fortran OOP 很陌生,并且在初始化父类型和派生类型时遇到了一些问题。我有一个包含父类型的模块object
(对不起这个词的过度使用..)和它的派生类型circle
,它有额外的radius
字段。
我现在需要初始化object
类型的方式需要对半径使用虚拟参数,我想避免这种方式。所以目前我有什么工作,但我想知道一种更好的方法来做到这一点,因为如果我object
将来需要进一步派生类型,它似乎不太实用。
我想在这个意义上使用object
作为抽象父类型会有所帮助吗?或者使用通用程序,但我真的不知道该怎么做。
代码如下。
module objectMod
implicit none
type :: object
real,allocatable :: x(:,:) ! position vector (points) --- (M,{i,j})
real :: centre(2) ! centre of the object
integer :: M=50 ! number of Lagrangian points of the object (default)
real :: eps=0.1 ! kernel of the surface (default)
contains
procedure :: init=>init_object
end type object
contains
subroutine init_object(a,centre,radius,M,eps)
implicit none
class(object),intent(inout) :: a
real,intent(in) :: centre(2)
integer,intent(in),optional :: M
real,intent(in),optional :: eps
real,intent(in),optional :: radius ! ignored for object
if(present(M)) a%M = M
if(.not.allocated(a%x)) allocate(a%x(a%M,2))
a%centre = centre
if(present(eps)) a%eps = eps
end subroutine init_object
end module objectMod
module geomMod
use objectMod
implicit none
real,parameter :: PI = 3.14159265
type,extends(object) :: circle
real :: radius ! radius
contains
procedure :: init=>init_circle
end type circle
contains
subroutine init_circle(a,centre,radius,M,eps)
implicit none
class(circle),intent(inout) :: a
real,intent(in) :: centre(2)
real,intent(in),optional :: radius
integer,intent(in),optional :: M
real,intent(in),optional :: eps
integer :: i
real :: dtheta
! object type attributes initialization
a%centre = centre
if(present(M)) a%M = M
if(.not.allocated(a%x)) allocate(a%x(a%M,2))
if(present(eps)) a%eps = eps
! circle type attributes initialization
a%radius = radius
dtheta = 2.*PI/real(a%M-1)
do i = 1,a%M
a%x(i,1) = a%radius*cos(dtheta*(i-1))+a%centre(1)
a%x(i,2) = a%radius*sin(dtheta*(i-1))+a%centre(2)
end do
end subroutine init_circle
end module geomMod