subprogramas - declaración de clase fortran de argumento ficticio
guia fortran (2)
Me gustaría tener un tipo derivado, a
, que está vacío. De este tipo derivado me gustaría definir más tipos que amplíen a. Supongamos que todas estas extensiones de tipo contienen algún nombre generic
procedimiento, value
, es decir, value => valuea1
, value => valuea2
, etc.
Si luego quiero pasar las variables de la clase a a algún otro procedimiento, necesito declarar el argumento ficticio relevante de ese procedimiento con la class(a)
. Sin embargo, si hago esto, hacer referencia al value
del argumento ficticio conduce a la falla de compilación porque la clase a está realmente vacía, solo las extensiones de tipo contienen el procedimiento.
Podría prescindir de esto teniendo algún procedimiento llamado value
dentro de la definición de tipo de a (luego anulando en las extensiones). Sin embargo, dado que nunca quiero declarar ningún objeto con el tipo a, parece desordenado. Es posible evitar esto?
Sí, puede declarar un procedimiento enlazado por tipo incluso para un tipo abstract
. Puede ser un procedimiento enlazado de tipo real, o simplemente una 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
De esta forma, no puede crear variables de type(a)
, pero puede crear tipos extendidos que implementen sus propias versiones de value
.
Similar a la respuesta de @VladimirF, pero tomando su aclaración de que
Realmente no necesito la resolución genérica; valuea1 y valuea2 aceptan el mismo tipo de argumentos para el problema que tengo en mente, solo quiero vincularme a valuea1 en una extensión de tipo y a valuea2 en otra extensión de tipo.
Aquí, entonces, el tipo base (abstracto) define un value()
procedimiento de límite de tipo diferido value()
con una class(a)
toma de interfaz class(a)
como el argumento pasado. Se pueden agregar otros argumentos. Cada tipo de extensión define / anula este procedimiento de tipo vinculado con su propio procedimiento.
Esto significa que en nuestra test_sub
subrutina final test_sub
el argumento ficticio de class(a)
tiene un %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
Esto produce salida
Valor de a1
Valor de a2
Valor de a1
Valor de a2