gpt4 book ai didi

oop - 如何在抽象派生类型中设计 PRIVATE OVERRIDABLE 过程?

转载 作者:行者123 更新时间:2023-12-03 17:36:04 27 4
gpt4 key购买 nike

通常,抽象类型是后代派生类型的模型。如果类型中包含的过程被推迟,则该类型中的过程应该是 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 是非抽象类型并继承了延迟绑定(bind),因此必须重写过程(加法和减法)。但是程序在my_numeric_type中定义为private,也就是说它们不能在模块test1之外被覆盖,所以上面的my_integer类型是无效的。我该怎么办 ?

最佳答案

来自 fortran 2018 标准草案第 7.5.5 节第 9 段:

A public type-bound procedure is accessible via any accessible object of the type. A private type-bound procedure is accessible only within the module containing the type definition, and within its descendants.


这意味着可以实现 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
这个约束( ParentChild 必须在同一个模块中声明)会导致大文件,并可能导致依赖排序问题。有几种方法可以改善这种情况:
  • 使用submodules分解模块。例如Parent可以有自己的子模块,每个Child可以有自己的子模块。
  • 而不是使用private延迟过程,对应该被视为私有(private)的延迟过程使用命名约定,例如尾随下划线(所以 add_Parent_add_Child_ )。
  • 关于oop - 如何在抽象派生类型中设计 PRIVATE OVERRIDABLE 过程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48023393/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com