Fortran中也可以定义类似于C++中的类(class),若单单只有变量,没有函数的定义,那么就类似于C/C++中的结构体(struct)。Fortran中是通过关键字type来实现面向对象的。type的结构为:

1
2
3
4
5
type 类名
定义变量
contains
定义类过程
end type 类名

和C++中不同的是,在type只能声明类过程(类函数),具体实现需要放到type外面去。从而很容易想到,可以将type的声明和具体实现放到module中封装起来,会变的非常方便。

type中的公有和私有成员的声明和module中的不太一样,若要将成员都变为私有,需要在type内成员定义前进行声明private,type中不允许整体声明为公有,若要在私有环境中声明公有成员,则需将public当作成员属性进行声明(不过默认为公有环境,也可用private将成员进行私有化声明)。

type中暂时还没有实现构造函数(constructor )的实现方式,成员变量需要一一赋值。但是可以利用final声明析构函数(destructor)。

type也有类似C++中的抽象类和多态的实现,还可利用class关键字在运行时(runtime)识别父类或派生类型。可用select type-type is结构判断当前的类在有继承关系的类中具体指的哪个类。

type中类函数定义的过程中,需要显式的给出类似C++中的”this”指针,这里更像是Python中的”self”。

例如一个circle的type:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1    module shapes
2 implicit none
3 private
4 public :: circle
5 type circle
6 private
7 real :: pi=3.1415927
8 real, public :: r
9 contains
10 procedure :: area
11 procedure :: length
12 end type circle
13 contains
14 real function area(this)
15 implicit none
16 class(circle), intent(in) :: this
17 area = (this%pi)*(this%r)**2
18 end function area
19 subroutine length(this, lens)
20 implicit none
21 class(circle), intent(in) :: this
22 real, intent(out) :: lens
23 lens = 2*(this%pi)*(this%r)
24 end subroutine length
25 end module shapes
26 program main
27 use shapes
28 implicit none
29 real :: r=3.0, lens
30 type(circle) :: cir
31 cir%r = r
32 write(*,*) cir%area()
33 call cir%length(lens)
34 write(*,*) lens
35 end program main

这里声明了一个名为circle的type,其中有类成员pi是私有的,而r是公有的,当然也可以都设置为私有,然后利用”set_”一样的函数去赋值,这样也会更安全。

这里定义了两个公有类函数(对象方法)。类函数声明需要用到procedure,这个关键字非常的有用,除了用来绑定类函数以外,还可以用来绑定操作符(operator)重载功能。这里显式定义this的时候,用到了class关键字,形式上若是没有type的继承,这里替换成type也是可以的,但是Fortran中强制要使用class,以防止派生类访问父类中的函数对象(还有多态)出现不必要的错误。class就是用来识别当前类对象是通过在一系列派生类中是通过哪个类进行声明的。

这里实例化了一个circle类的对象cir。调用类函数需要用到%操作符,这个和C++中的点操作符.是一样的。Fortran中类似C++中->的操作符为=>。

往后还会介绍关于在Fortran中抽象类和多态方法的实现方式。