动态选择对象类型

时间:2015-01-28 15:09:30

标签: oop fortran object-type

我试图为数值解算器制作灵活的用户界面。问题是我无法制定如何实现初始条件几何(矩形,球体等)的动态选择。我尝试将抽象类initial_conditions_geometry用作子类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类定义,它包含初始条件几何和分布:

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

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

1 个答案:

答案 0 :(得分:1)

你所拥有的是非常接近工作,我认为你只是有一个误解。

  

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

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

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

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

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

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

如果你有编译器支持多态变量的内部赋值(或使用定义的赋值)。