通常,抽象类型是后代派生类型的模型。如果延迟,则类型中包含的过程应该是PUBLIC,因为不能从模块本身引用或覆盖PRIVATE类。但是,如果我希望每个后代都有一个相同的功能性PRIVATE过程来执行某些操作(例如,测试它的实例的初始化状态),我该如何设计ABSTRACT派生类型?我是否必须在每个后代中手动定义它们,或者我可以将模型放在摘要中并在后代中实现它? 这是一个例子:
module test1
implicit none
private
public :: my_numeric_type
type, abstract :: my_numeric_type
contains
private
procedure(op2), deferred :: add
procedure(op2), deferred :: subtract
generic, public :: operator(+) => add
generic, public :: operator(-) => subtract
end type my_numeric_type
abstract interface
function op2(a, b) result(r)
import :: my_numeric_type
class(my_numeric_type), intent(in) :: a, b
class(my_numeric_type), allocatable :: r
end function op2
end interface
end module test1
module test2
use test1, only: my_numeric_type
implicit none
type, extends(my_numeric_type) :: my_integer
private
integer :: value
contains
private
procedure, public :: add => add_my_integer
procedure, public :: subtract => subtract_my_integer
end type my_integer
contains
function add_my_integer(a, b) result(r)
class(my_integer), intent(in) :: a
class(my_numeric_type), intent(in) :: b
class(my_numeric_type), allocatable :: r
! DO SOME ADDITION.
end function add_my_integer
function subtract_my_integer(a, b) result(r)
class(my_integer), intent(in) :: a
class(my_numeric_type), intent(in) :: b
class(my_numeric_type), allocatable :: r
! DO SOME SUBTRACTION.
end function subtract_my_integer
end module test2
在该示例中,后代派生类型my_integer是非抽象类型并且继承了延迟绑定,因此必须重写过程(加和减)。但是这些过程在my_numeric_type中被定义为private,也就是说它们不能在模块test1之外被覆盖,因此上面的my_integer类型无效。我该怎么办?
答案 0 :(得分:0)
来自 fortran 2018 标准草案,第 7.5.5 节,第 9 段:
<块引用>公共类型绑定过程可通过该类型的任何可访问对象访问。私有类型绑定过程只能在包含类型定义的模块及其后代中访问。
这意味着可以实现 private
deferred
过程,但前提是已实现的过程与延迟过程在同一模块中声明。
例如:
module m
implicit none
type, abstract :: Parent
contains
procedure(add_Parent), deferred, private :: add
generic, public :: operator(+) => add
end type
abstract interface
function add_Parent(lhs,rhs) result(output)
import :: Parent
class(Parent), intent(in) :: lhs
class(Parent), intent(in) :: rhs
class(Parent), allocatable :: output
end function
end interface
type, extends(Parent) :: Child
integer :: contents
contains
procedure, private :: add => add_Child
end type
contains
function add_Child(lhs,rhs) result(output)
class(Child), intent(in) :: lhs
class(Parent), intent(in) :: rhs
class(Parent), allocatable :: output
select type(rhs); type is(Child)
output = Child(lhs%contents+rhs%contents)
end select
end function
end module
program p
use m
type(Child) :: a,b
class(Parent), allocatable :: c
a = Child(3)
b = Child(5)
c = a+b
select type(c); type is(Child)
write(*,*) c%contents
end select
end program
此约束(Parent
和 Child
必须在同一个模块中声明)会导致文件过大,并可能导致依赖项排序出现问题。有几种方法可以改善这种情况:
submodules
分解模块。例如Parent
可以有自己的子模块,每个 Child
可以有自己的子模块。private
延迟过程,而是使用延迟过程的命名约定,应该将其视为私有的,例如尾随下划线(所以 add_Parent_
和 add_Child_
)。