考虑以下类型
TYPE, ABSTRACT:: base
...
CONTAINS
SUBROUTINE sanity_check
END SUBROUTINE
END TYPE
TYPE, EXTENDS(base):: concrete1
...
END TYPE
TYPE, EXTENDS(base):: concrete2
...
END TYPE
,其中...
表示一些与问题无关的数据。代码中定义了concrete1
和concrete2
类型的构造函数,并实现了sanity_check
子程序。
现在,我想自动在concrete1
和concrete2
构造函数的末尾执行sanity_check
。换句话说,sanity_check
应该在扩展base
的任何类型的构造函数的末尾执行,而不需要在构造函数中显式调用它。如果其他程序员要编写扩展base
的类型,检查所有数据是否已被其扩展类型正确初始化,而不需要程序员显式调用sanity_check
,这将是有用的。
这是可能的吗?我已经看到为抽象类型定义接口是可能的,但我不知道它是否可以用来实现我上面描述的(或者它是否有任何用处,因为抽象类型不能通过定义实例化)。
正如francescalus所说,不可能完全做到你想做的。
然而,如果你所有的构造函数都使用相同的参数,那么你可以通过用初始化子例程替换你的构造函数来相当接近你想要的结果。
你可以给base
类一个initialise
子程序,它通过首先调用deferred
helper
子程序来初始化对象,然后调用sanity_check
。
base
类看起来像:
module base_module
implicit none
type, abstract :: base
contains
procedure :: sanity_check
procedure :: initialise
procedure(helper_base), deferred :: helper
end type
contains
subroutine sanity_check(this)
class(base), intent(in) :: this
end subroutine
subroutine initialise(this, args)
class(base), intent(out) :: this
integer, intent(in) :: args
call this%helper(args)
call this%sanity_check
end subroutine
abstract interface
subroutine helper_base(this, args)
import base
class(base), intent(out) :: this
integer, intent(in) :: args
end subroutine
end interface
end module
每个子类将重载helper
,initialise
子程序将根据需要自动调用sanity_check
。
子类看起来像:
module concrete_module
implicit none
type, extends(base) :: concrete
contains
procedure :: helper => helper_concrete
end type
contains
subroutine helper_concrete(this, args)
class(concrete), intent(out) :: this
integer, intent(in) :: args
end subroutine
end module
你将构造一个concrete
对象,例如:
type(concrete) :: foo
integer :: args = 1
call foo%initialise(args)
如果您愿意,您可以通过编写调用initialise
的瘦包装器来重新引入foo = concrete(args)
语法,尽管这可能比手动编写构造函数要做更多的工作。