Oop 如何在抽象派生类型中设计私有可重写过程?

Oop 如何在抽象派生类型中设计私有可重写过程?,oop,fortran,private,abstract,Oop,Fortran,Private,Abstract,通常,抽象类型是后代派生类型的模型。如果类型中包含的过程被延迟,则该类型中包含的过程应该是公共的,因为私有过程不能在模块本身之外被引用或重写。但是,如果我希望每个子体都有相同的函数私有过程来执行某些操作(例如,测试其实例的初始化状态),那么如何设计抽象派生类型呢?我是否必须在每个子体中手动定义它们,或者我是否可以抽象地放置一个模型并在子体中实现它? 下面是一个例子: module test1 implicit none private public :: my_nume

通常,抽象类型是后代派生类型的模型。如果类型中包含的过程被延迟,则该类型中包含的过程应该是公共的,因为私有过程不能在模块本身之外被引用或重写。但是,如果我希望每个子体都有相同的函数私有过程来执行某些操作(例如,测试其实例的初始化状态),那么如何设计抽象派生类型呢?我是否必须在每个子体中手动定义它们,或者我是否可以抽象地放置一个模型并在子体中实现它? 下面是一个例子:

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_类型中定义的私有过程,也就是说,它们不能在模块test1之外被重写,因此上面的my_integer类型无效。我该怎么办?

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

公共类型绑定过程可以通过该类型的任何可访问对象进行访问。私有类型绑定过程只能在包含类型定义的模块及其子代中访问

这意味着可以实现
private
延迟的
过程,但前提是所实现的过程与延迟的过程在同一模块中声明

例如:

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
此约束(父级和子级必须在同一模块中声明)可能会导致大文件,并可能导致依赖项排序问题。有几种方法可以改善这种情况:

  • 使用
    子模块
    分解模块。e、 g.
    父级
    可以有自己的子模块,每个
    子级
    可以有自己的子模块
  • 不要使用
    private
    deferred procedures,而应使用应被视为private的延迟过程的命名约定,例如尾随下划线(因此
    add\u Parent\u
    add\u Child\u

螺纹已更新。非常感谢,@Vladimir。我想这和它有很多共同点。它是否可以重复?@Vladimir,我看不出这个问题和那个问题之间有什么联系。@Vladimir,在你建议的线程中,两个派生类型中的类型绑定过程都是使用默认的公共访问权限定义的。但是我的问题是实现一个私有的延迟类型绑定过程。