动态选择对象类型
Dynamically choose object type
我正在尝试为数值求解器制作灵活的用户界面。问题是我无法制定如何实现初始条件几何体(矩形、球体等)的动态选择。我尝试使用抽象 class initial_conditions_geometry
作为带有子 classes rectangular
和 sphere
的父对象,它们指定某些属性并实现方法 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
如果编译器支持对多态变量进行内部赋值(或使用定义赋值)。
我正在尝试为数值求解器制作灵活的用户界面。问题是我无法制定如何实现初始条件几何体(矩形、球体等)的动态选择。我尝试使用抽象 class initial_conditions_geometry
作为带有子 classes rectangular
和 sphere
的父对象,它们指定某些属性并实现方法 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
如果编译器支持对多态变量进行内部赋值(或使用定义赋值)。