我想知道是否有可能(如果有的话如何)在运行时让Fortran TYPE继承另一个TYPE。例如,用户提供一个输入文件,说明需要继承哪个TYPE。下面是一个例子,
MODULE A_MOD
type A
real(8) :: m, n
end type
END MODULE
对于B_MOD
也是一样MODULE B_MOD
type B
real(8) :: param
end type
END MODULE
A和B都有在模块中定义的过程和其他元素。我现在有了另一个TYPE C,我希望它根据用户输入继承A或B。一般来说,
input = A ! provided by user
...
type, extends(input) :: C
end type
我可以在Python中做类似的事情。我还不是很熟悉Fortran多态性,所以任何帮助将是感激的!
不,这不可能。编译器需要在编译时知道类型的内存需求,因此运行时类型定义是不可能的。
一个可能的解决方法是定义两个C
类型,CA
和CB
,然后使用工厂方法在运行时选择使用哪个类型。
代码可能看起来像这样:
module m
type, abstract :: Base
contains
procedure(hi_Base), deferred :: hi
end type
abstract interface
subroutine hi_Base(self)
import :: Base
class(Base), intent(in) :: self
end subroutine
end interface
type, extends(Base) :: A
contains
procedure :: hi => hi_A
end type
type, extends(Base) :: B
contains
procedure :: hi => hi_B
end type
type, extends(A) :: CA
end type
type, extends(B) :: CB
end type
contains
subroutine hi_A(self)
class(A), intent(in) :: self
write(*,*) "Hi, I'm an A!"
end subroutine
subroutine hi_B(self)
class(B), intent(in) :: self
write(*,*) "Hi, I'm a B!"
end subroutine
function factory(switch) result(output)
logical, intent(in) :: switch
class(Base), allocatable :: output
if (switch) then
output = CA()
else
output = CB()
endif
end function
end module
program p
use m
implicit none
class(Base), allocatable :: foo
foo = factory(.true.)
call foo%hi()
foo = factory(.false.)
call foo%hi()
end program
话虽如此,如果C
有A
或B
,而不是继承A
或B
,你可能会有更好的运气。它看起来像
module m
type, abstract :: Base
contains
procedure(hi_Base), deferred :: hi
end type
abstract interface
subroutine hi_Base(self)
import :: Base
class(Base), intent(in) :: self
end subroutine
end interface
type, extends(Base) :: A
contains
procedure :: hi => hi_A
end type
type, extends(Base) :: B
contains
procedure :: hi => hi_B
end type
type :: C
class(Base), allocatable :: foo
end type
interface C
module procedure new_C
end interface
contains
subroutine hi_A(self)
class(A), intent(in) :: self
write(*,*) "Hi, I'm an A!"
end subroutine
subroutine hi_B(self)
class(B), intent(in) :: self
write(*,*) "Hi, I'm a B!"
end subroutine
function new_C(switch) result(self)
logical, intent(in) :: switch
type(C) :: self
if (switch) then
self%foo = A()
else
self%foo = B()
endif
end function
end module
program p
use m
implicit none
type(C) :: bar
bar = C(.true.)
call bar%foo%hi()
bar = C(.false.)
call bar%foo%hi()
end program