【发布时间】:2015-12-08 00:55:32
【问题描述】:
有没有办法使派生类型具有接口,以便为泛型派生类型调用特定的模块过程?我可能没有正确解释这一点,但这是我想做的简短示例代码:
module test_mod
implicit none
private
public :: type_AB ! This is what I'd like to do...
public :: init,apply,delete
interface type_AB ! This is what I'd like to do...
module type type_AB
end interface
interface init; module procedure init_A; end interface
interface init; module procedure init_B; end interface
interface apply; module procedure apply_A; end interface
interface apply; module procedure apply_B; end interface
type type_A
integer :: x
end type
type type_B
integer,dimension(3) :: x
end type
contains
subroutine init_A(AB,x)
implicit none
type(type_A),intent(inout) :: AB
integer,intent(in) :: x
AB%x = x
end subroutine
subroutine init_B(AB,x)
implicit none
type(type_B),intent(inout) :: AB
integer,dimension(3),intent(in) :: x
AB%x = 2
end subroutine
subroutine apply_A(AB,x)
implicit none
type(type_A),intent(inout) :: AB
integer,intent(in) :: x
AB%x = AB%x + x
end subroutine
subroutine apply_B(AB,x)
implicit none
type(type_B),intent(inout) :: AB
integer,dimension(3),intent(in) :: x
AB%x = AB%x + x
end subroutine
end module
在使用 test_mod 时,我可以简单地使用 type_AB 而不是指定 type_A 或 type_B。我知道我可以只指定两个对象,但是除了等级之外它们基本上是相同的,所以有一种组合/多态对象会很好,但我宁愿不嵌入第二个派生类型一。例如:
type type_AB
type(type_A) :: A
type(type_B) :: B
end type
因为它会使类文件更加混乱(如果 AB 是 type_AB 类型,则引用 x 变为例如 AB%A%x 而不是 AB%x)。如果这是唯一的方法,那么我想我可以做到,但我想知道是否还有其他选择。此外,如果使用 type_A,则使用组合/多态方法会增加需要在 type_B 中释放任何内容的烦恼,反之亦然..
我想其他人可能会以更好的方式提出这个问题,但是当我查看示例时,大多数人似乎都使用 f2003 标准,我对此有点不熟悉。非常感谢您回答或改进问题的任何帮助,谢谢。
更新:
我尝试按照建议实现类型扩展,但这是我所能得到的。
module type_AB_mod
implicit none
private
public :: type_AB ! This is what I'd like to do...
public :: init
interface init; module procedure init_A; end interface
interface init; module procedure init_B; end interface
type type_AB
logical :: L
end type
type, extends(type_AB) :: type_A
integer :: x
end type
type, extends(type_AB) :: type_B
integer,dimension(3) :: x
end type
contains
subroutine init_A(AB,x)
implicit none
type(type_A),intent(inout) :: AB
integer,intent(in) :: x
AB%x = x
write(*,*) 'Init A'
end subroutine
subroutine init_B(AB,x)
implicit none
type(type_B),intent(inout) :: AB
integer,dimension(3),intent(in) :: x
AB%x = 2
write(*,*) 'Init B'
end subroutine
end module
program test
use type_AB_mod
implicit none
type(type_AB) :: AB
integer :: i
integer,dimension(3) :: j
call init(AB,i)
call init(AB,j)
end program
我收到两个错误,它们都是:
There is no specific subroutine for the generic 'init'
参考call init(AB,i)和call init(AB,j)
更新 2:
我已调整示例以包含提供的答案:
module type_AB_mod
implicit none
private
public :: type_AB ! This is what I'd like to do...
public :: init
interface init; module procedure init_A; end interface
interface init; module procedure init_B; end interface
type type_AB
end type
type, extends(type_AB) :: type_A
integer :: x
end type
type, extends(type_AB) :: type_B
integer,dimension(3) :: x
end type
contains
subroutine init_A(AB,x)
implicit none
type(type_AB),allocatable,intent(inout) :: AB
integer,intent(in) :: x
allocate(AB, source=type_A(x=x))
write(*,*) 'Init A'
end subroutine
subroutine init_B(AB,x)
implicit none
type(type_AB),allocatable,intent(inout) :: AB
integer,dimension(3),intent(in) :: x
allocate(AB, source=type_B(x=x))
write(*,*) 'Init B'
end subroutine
end module
program test
use type_AB_mod
implicit none
class(type_AB),allocatable :: AB
integer :: i
integer,dimension(3) :: j
call init(AB,i)
deallocate(AB)
call init(AB,j)
deallocate(AB)
end program
但我仍然得到编译器错误:
allocate(AB, source=type_B(x=x))
1 2
Error: Type of entity at (1) is type incompatible with source-expr at (2):
allocate(AB, source=type_A(x=x))
1 2
Error: Type of entity at (1) is type incompatible with source-expr at (2):
【问题讨论】:
-
你不只是在寻找类型和扩展类型(Fortran-speak for sub-types)吗?将你的
type_a和type_b扩展为超类型(如果你愿意,可以称之为type_ab)。本文 (pgroup.com/lit/articles/insider/v3n1a3.htm) 及其其他部分很好地介绍了 Fortran 的 OO 功能。 -
我不清楚
extends type将如何工作,看来我仍然必须在 test_mod 之外使用 type_a 或 type_b ...我希望只使用 type_ab,因为 init / apply 应该由传递的参数确定(它们具有不同的等级)。这有意义吗? -
AB是type_AB类型,而您的泛型inits 适用于type_A和type_B类型。所以确实没有对手。如果您想使用多态性,那么这将需要与不使用的方法略有不同。不过,您的问题并不清楚您是否这样做。 [如果不这样做,只需在声明时选择AB的类型,就可以了。] -
我只想从 type_AB_mod 之外查看 type_AB。如果我将
type(type_A),intent(inout) :: AB和type(type_B),intent(inout) :: AB更改为type(type_AB),intent(inout) :: AB,则会收到2 个错误消息:“(1) 处的'x' 不是'type_ab' 结构的成员” -
对于新的错误,您必须在init子程序中使用
class(type_AB), ...,而不是type(type_AB)。
标签: interface module fortran polymorphism overloading