Fortran面向对象(三)
继续Fortran面向对象的学习。
Unlimited polymorphic types
class(*)
类型称为无限制多态类型,必须拥有pointer或allocatable属性。括号中用*
代替具体的类名表示可以是任意类。(联想C语言中void *
通用指针概念)
一般不直接使用无限制多态类型,常用作过程的哑元,使用select type
结构转换为指定类型使用。
CLASS(*), POINTER :: unlimited_ptr
unlimited_ptr => base_target
SELECT type(unlimited_ptr)
TYPE IS (base)
PRINT *, "base type: component value: ", unlimited_ptr%i
TYPE IS (child)
PRINT *, "child type: component values: ", unlimited_ptr%i,unlimited_ptr%j
END SELECT
pass vs nopass
前面提到类方法调用时,我们不会传递第一个对象参数,因为方法调用隐含传递了。这一约定可以通过pass
和nopass
属性改变。
通过pass
可以显式指定类方法的对象参数名,同时对象参数不需要放在第一个参数位置上。
type, extends(mytype) :: mynewtype
real :: extra
contains
procedure, pass(value) :: write => write_mynewtype
end type mynewtype
! type-bound procedure definition
subroutine write_mynewtype(lun, value) !对象value作为第二个参数
integer,intent(in) :: lun
class(mynewtype) :: value
call value%mytype%write(lun)
end subroutine write_mynewtype
类方法调用与之前的完全相同。
call v%write(lun) !完全相同
call write_mynewtype(lun, v) ! 普通调用方法,参数顺序必须与定义一致
通过nopass
指定类方法调用时不能省掉对象参数。
procedure, nopass :: write => write_mynewtype
!调用
call v%write(lun, v)
Abstract classes and deferred procedure
通过abstract
定义抽象类,一般用作基类模板。其中类方法可以“延迟”(deferred)到继承类定义中实现。
我们不希望在基类实现具体的类方法,因为继承类可能还需要根据实际情况进行重置,不如只声明一个过程接口,推迟到后面继承类中实现。
首先定义一个抽象类mytemplate:
type, abstract :: mytemplate
...
contains
procedure(calculate_template), deferred :: calc ! deferred keyword
end type mytemplate
mydata类继承mytemplate类,同时实现类方法clac:
type, extends(mytemplate) :: mydata
...
contains
procedure(calculate_template) :: calc => calc_mydata
end type mydata
其中procedure(calculate_template) :: calc
声明语法和变量声明很相似(比如integer :: a
),可以理解为:声明一个calc过程,其函数签名(参数和返回值类型)要符合calculate_template接口要求。
在上面的抽象类mytemplate定义中,延迟的类方法calc需要让编译器知道过程参数和返回值(即函数签名),因此需要通过abstract interface
语法声明过程模板,描述过程的参数及返回值信息,但不会具体实现,留待后续实际过程中实现。
abstract interface
subroutine calculate_template( t, x, y )
import :: mytemplate
class(mytemplate) :: t
real :: x, y
end subroutine calculate_template
end interface
Procedure pointers
类似于指针变量可以指向变量目标(target),Fortran标准增加了过程指针,用于指向过程(procedure)(联想C语言中的函数指针)。
! declare procedure pointer p
procedure(calculate_template), pointer :: p
! p point to subroutine my_calculation
p => my_calculation
! call procedure
call p( t, x, y )
call my_calculation( t, x, y )


怎么收藏这篇文章?