问题
I would like to have a derived type, a
, which is empty. From this derived type I would like to define further types which extend a. Suppose all of these type extensions contain some generic
procedure name, value
, i.e value => valuea1
, value => valuea2
, etc.
If I then want to pass variables of class a to some other procedure, I need to declare the relevant dummy argument of that procedure with class(a)
. If I do this, however, then referencing the value
of the dummy argument leads to compilation failure because the class a is actually empty - only the type extensions contain the procedure.
I could presumably get around this by having some procedure called value
inside the type definition of a (then overriding in the extensions). However, given that I never want to declare any object with type a, this seems messy. It it possible to get around this?
回答1:
Yes, you can declare a type bound procedure even for an abstract
type. It can be a real type bound procedure, or just an abstract interface
.
type, abstract :: a
contains
procedure :: valuea1, valuea2
generic value :: value => valuea1, valuea2
end type
abstract interface
! the headers of valuea1, valuea2 here
! they should have a passed dummy argument class(a)
! and some other argument for the generic resolution
! for example:
subroutine valua1(self, x)
class(a), intent(in) :: self
real, intent(inout) :: x
end subroutine
subroutine valua2(self, x)
class(a), intent(in) :: self
integer, intent(inout) :: x
end subroutine
end interface
This way you cannot create variables of type(a)
, but you can make extended types which implement their own versions of value
.
回答2:
Similar to the answer by @VladimirF, but taking your clarification that
I don't actually need the generic resolution; valuea1 and valuea2 accept the same type of arguments for the problem that I have in mind, I just want to bind to valuea1 in one type extension and valuea2 in another type extension.
Here, then, the base (abstract) type defines a deferred type-bound procedure value()
with an interface taking class(a)
as the passed argument. Other arguments can be added. Each extending type defines/overrides this type-bound procedure with its own procedure.
This means than in our final subroutine call test_sub
the class(a)
dummy argument does have a %value()
.
module types
! The base type
type, abstract :: a
contains
procedure(value_if), deferred :: value
end type a
! The interface for the type-bound procedures
abstract interface
subroutine value_if(var)
import a
class(a) var
end subroutine value_if
end interface
! The extending types, overriding the value subroutine
type, extends(a) :: a1
contains
procedure :: value => value_a1
end type a1
type, extends(a) :: a2
contains
procedure :: value => value_a2
end type a2
contains
subroutine value_a1(var)
class(a1) var
print*, "Value of a1"
end subroutine value_a1
subroutine value_a2(var)
class(a2) var
print*, "Value of a2"
end subroutine value_a2
end module types
program test
use types
type(a1) x
type(a2) y
call x%value
call y%value
call test_sub(x)
call test_sub(y)
contains
subroutine test_sub(var)
class(a) var
call var%value ! This is defined
end subroutine test_sub
end program test
This produces output
Value of a1
Value of a2
Value of a1
Value of a2
来源:https://stackoverflow.com/questions/22334675/fortran-class-declaration-of-dummy-argument