Я новичок в 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