Объявление класса Фортран фиктивного аргумента
Я хотел бы иметь производный тип, a
, который пуст. Из этого производного типа я хотел бы определить другие типы, которые расширяют. Предположим, что все эти расширения типа содержат некоторые generic
название процедуры, value
т.е. value => valuea1
, value => valuea2
, так далее.
Если я затем хочу передать переменные класса a какой-либо другой процедуре, мне нужно объявить соответствующий фиктивный аргумент этой процедуры с помощью class(a)
, Если я сделаю это, однако, то ссылка на value
аргумента-пустышки приводит к сбою компиляции, потому что класс a фактически пуст - только процедуры расширения содержат процедуру.
Я мог предположительно обойти это, имея некоторую процедуру под названием value
внутри определения типа a (затем переопределяя в расширениях). Однако, учитывая, что я никогда не хочу объявлять какой-либо объект с типом a, это кажется грязным. Можно ли обойти это?
2 ответа
Да, вы можете объявить процедуру, связанную с типом, даже для abstract
тип. Это может быть процедура, связанная с реальным типом, или просто 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
Таким образом, вы не можете создавать переменные type(a)
, но вы можете создавать расширенные типы, которые реализуют свои собственные версии value
,
Похоже на ответ @VladimirF, но, принимая во внимание, что
Мне на самом деле не нужно общее разрешение; valuea1 и valuea2 принимают тот же тип аргументов для проблемы, которую я имею в виду, я просто хочу связать valuea1 в одном расширении типа и valuea2 в другом расширении типа.
Здесь, тогда, базовый (абстрактный) тип определяет отложенную процедуру с привязкой к типу value()
с интерфейсом, принимающим class(a)
как переданный аргумент. Другие аргументы могут быть добавлены. Каждый расширяющий тип определяет / переопределяет эту связанную с типом процедуру своей собственной процедурой.
Это значит, чем в нашем последнем вызове подпрограммы test_sub
class(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
Это производит вывод
Значение а1
Значение а2
Значение а1
Значение а2