动态选择对象类型

Dynamically choose object type

我正在尝试为数值求解器制作灵活的用户界面。问题是我无法制定如何实现初始条件几何体(矩形、球体等)的动态选择。我尝试使用抽象 class initial_conditions_geometry 作为带有子 classes rectangularsphere 的父对象,它们指定某些属性并实现方法 in_bounds 对于几何:

type    ,abstract   ::  initial_conditions_geometry
    contains
        procedure (in_bounds)   ,deferred    :: in_bounds 
end type

abstract interface 
    logical function in_bounds(this,coordinates)
        import :: rkind
        import :: initial_conditions_geometry
        class(initial_conditions_geometry)  ,intent(in) :: this
        real(rkind)     ,dimension (:)      ,intent(in) :: coordinates
    end function in_bounds
end interface

type    ,extends(initial_conditions_geometry) :: rectangular
    integer ,dimension(:,:) ,allocatable    :: rectangular_bounds
contains
    procedure   :: in_bounds => in_bounds_rectangular
end type 

type    ,extends(initial_conditions_geometry) :: sphere
    integer ,dimension(:,:) ,allocatable    :: sphere_bounds
    integer ,dimension(:)   ,allocatable    :: sphere_center
contains
    procedure   :: in_bounds => in_bounds_sphere
end type

interface rectangular
    procedure constructor_rectangular
end interface

interface sphere
    procedure constructor_sphere
end interface

这里是 initial_conditions_layer class 定义,其中包括初始条件几何和分布:

type    :: initial_conditions_layer
    class(initial_conditions_geometry)  ,allocatable    :: layer_geometry
    type(initial_conditions_distribution)               :: distributor
end type   

interface initial_conditions_layer
    procedure   constructor
end interface

问题是:如何设法为 initial_conditions_layer 创建动态(取决于某些文本文件中的几何类型)设置 layer_geometry 类型(矩形、球体等)的构造函数?

编辑 也许添加一些我解决这个问题的尝试是有用的。 我尝试按如下方式组织 initial_conditions_layer 对象的构造函数:

type(initial_conditions_layer) function constructor(dimensions,layer_number,initial_conditions_data_file_unit)
    integer ,intent(in) :: layer_number
    integer ,intent(in) :: initial_conditions_data_file_unit
    integer ,intent(in) :: dimensions
    character(len=20)   :: layer_distribution_type
    character(len=20)   :: layer_geometry_name     

    call get_layer_properties(initial_conditions_data_file_unit,layer_number,layer_geometry_name,layer_distribution_type)

    select case(layer_geometry_name)
    case('rectangular')
        allocate(rectangular::constructor%layer_geometry)
    case('sphere')
        allocate(sphere::constructor%layer_geometry)
    end select

    select type(constructor%layer_geometry)
    type is(rectangular)
        constructor%layer_geometry = rectangular()
    type is(sphere)
        constructor%layer_geometry = sphere()
    end select
end function

但这需要 associate_name in select 类型构造。 Associate_name 应该是指向 initial_conditions_geometry 的指针,但不能将目标属性设置为派生类型字段。

你的东西已经很接近工作了,我想你只是误会了。

But this requires associate_name in select type construct. Associate_name should be a pointer to initial_conditions_geometry, but one cannot set target attribute to derived type field.

在这种情况下需要 associate-name,但无论 => 语法如何,都不涉及指针。然后,您可以在不进行其他更改的情况下拥有

select type(clg => constructor%layer_geometry)
type is(rectangular)
    clg = rectangular()
type is(sphere)
    clg = sphere()
end select

或者,在这种简单的情况下,可以完全取消 select type 构造,并在您已有的 select case 中处理事情。

对每个构造函数使用源分配:

select case(layer_geometry_name)
case('rectangular')
    allocate(constructor%layer_geometry, source=rectangular())
case('sphere')
    allocate(constructor%layer_geometry, source=sphere())
end select

甚至

select case(layer_geometry_name)
case('rectangular')
    constructor%layer_geometry = rectangular()
case('sphere')
    constructor%layer_geometry = sphere()
end select

如果编译器支持对多态变量进行内部赋值(或使用定义赋值)。