Fortran中含可分配变量参数的类型绑定过程重载问题
Fortran面向对象编程:编译期未知类型下的过程重载疑问
我正在学习Fortran面向对象编程,对参数类型在编译期未知时,类型绑定过程重载的意义存在疑惑。以下通过示例逐步说明我的问题(示例仅用于提升Fortran技能):
第一个程序:类型绑定过程重载
module my_mod implicit none type :: my_type_t character(len=128) :: my_text contains procedure :: integer_print, real_print generic :: my_print => integer_print, real_print end type my_type_t contains subroutine integer_print(this, my_int) class(my_type_t), intent(in) :: this integer, intent(in) :: my_int write (*,"(a,a,i0)") trim(this%my_text),' integer ', my_int end subroutine integer_print subroutine real_print(this, my_real) class(my_type_t), intent(in) :: this real, intent(in) :: my_real write (*,"(a,a,f0.3)") trim(this%my_text),' real ', my_real end subroutine real_print end module my_mod program my_pgm use my_mod implicit none type(my_type_t) :: my_var my_var%my_text = "Hello" call my_var%my_print(10) call my_var%my_print(9.9) end program my_pgm
该程序得到预期结果:会根据my_print参数的类型(integer或real)自动调用integer_print或real_print。
第二个程序:使用抽象类型及派生类型
module my_mod implicit none type, abstract :: my_abstract_t end type my_abstract_t type, extends(my_abstract_t) :: my_int_t integer :: an_integer end type my_int_t type, extends(my_abstract_t) :: my_real_t real :: a_real end type my_real_t type :: my_type_t character(len=128) :: my_text contains procedure :: integer_print, real_print generic :: my_print => integer_print, real_print end type my_type_t contains subroutine integer_print(this, my_int) class(my_type_t), intent(in) :: this type(my_int_t), intent(in) :: my_int write (*,"(a,a,i0)") trim(this%my_text),' integer ', my_int%an_integer end subroutine integer_print subroutine real_print(this, my_real) class(my_type_t), intent(in) :: this type(my_real_t), intent(in) :: my_real write (*,"(a,a,f0.3)") trim(this%my_text),' real ', my_real%a_real end subroutine real_print end module my_mod program my_pgm use my_mod implicit none type(my_type_t) :: my_var type(my_int_t) :: my_int type(my_real_t) :: my_real my_var%my_text = "Hello" my_int%an_integer = 10 my_real%a_real = 9.9 call my_var%my_print(my_int) call my_var%my_print(my_real) end program my_pgm
my_int和my_real的类型在编译期已知,输出正确,且无论变量类型是my_int_t还是my_real_t,都能通过统一的my_var%my_print(...)调用,与第一个示例一致。
第三个程序:问题场景
program my_pgm use my_mod implicit none type(my_type_t) :: my_var class(my_abstract_t), allocatable :: my_number allocate(my_int_t::my_number) ! or allocate(my_real_t::my_number) my_var%my_text = "Hello" select type (my_number) type is (my_int_t) my_number%an_integer = 10 type is (my_real_t) my_number%a_real = 9.9 end select select type (my_number) type is (my_int_t) call my_var%my_print(my_number) type is (my_real_t) call my_var%my_print(my_number) end select end program my_pgm
my_number的类型在编译期未知,因此必须使用一段我认为冗余的代码:
select type (my_number) type is (my_int_t) call my_var%my_print(my_number) type is (my_real_t) call my_var%my_print(my_number) end select
我更希望像前两个示例那样只写一行call my_var%my_print(...)。请问是否可以得出结论:在此场景下过程重载没有意义,直接在select type块中调用integer_print和real_print更好?还是我有未理解的点?
Edit 1:优化后的程序
根据Francescalus的评论,我理解无法避免select type块,因此修改程序如下:
module my_mod implicit none type, abstract :: my_abstract_t end type my_abstract_t type, extends(my_abstract_t) :: my_int_t integer :: an_integer end type my_int_t type, extends(my_abstract_t) :: my_real_t real :: a_real end type my_real_t type :: my_type_t character(len=128) :: my_text contains procedure, private :: real_print, integer_print procedure, public :: my_print end type my_type_t contains subroutine integer_print(this, my_int) class(my_type_t), intent(in) :: this type(my_int_t), intent(in) :: my_int write (*,"(a,a,i0)") trim(this%my_text),' integer ', my_int%an_integer end subroutine integer_print subroutine real_print(this, my_real) class(my_type_t), intent(in) :: this type(my_real_t), intent(in) :: my_real write (*,"(a,a,f0.3)") trim(this%my_text),' real ', my_real%a_real end subroutine real_print subroutine my_print(this,my_number) class(my_type_t), intent(in) :: this class(my_abstract_t), intent(in) :: my_number select type (my_number) type is (my_int_t) call this%integer_print(my_number) type is (my_real_t) call this%real_print(my_number) end select end subroutine my_print end module my_mod program my_pgm use my_mod implicit none type(my_type_t) :: my_var class(my_abstract_t), allocatable :: my_number1, my_number2 my_number1 = my_int_t(an_integer = 10) my_number2 = my_real_t(a_real = 9.9) my_var%my_text = "Hello" call my_var%my_print(my_number1) call my_var%my_print(my_number2) end program my_pgm
期待各位的点评。
内容的提问来源于stack exchange,提问作者Stef1611
相关产品推荐
相关产品推荐

