Deferred procedures are those functions/subroutines that will be later implemented in a specific derived type. For instance, It can only be declared on abstract derived types.

To illustrate it, our problem requires a generic class that enforces the equal (==) property. Fortran classes must implement/overload the generic ‘==’ so it is possible to compare them. This can be usefull when using unlimited polymorphic types -class(*)-.

The code below declares a new generic class called eqObject_abs. When extended it enforces to implement the equal property.

type, abstract :: eqObject_abs !< equal unlimited polymorphic type
                               !< for non basic types
  contains
    procedure(iface_eq_object), deferred :: eq_object
    generic :: operator(==) => eq_object
end type eqObject_abs

Aside from the deferred statement, eq_object subroutine has attached an interface called iface_eq_object. It is mandatory when a type is deferred.

An abstract interface tells which procedure/function signature should expect when the type is extended. So all implementations will follow this header.

Note it requires to import any non basic type.

abstract interface
  logical function iface_eq_object(self, other)
  !< true if self and other are not the same
    import eqObject_abs
    !< it will evolve according to subtype
    class(eqObject_abs), intent(in) :: self
    class(eqObject_abs), intent(in) :: other
  end function iface_eq_object
end interface

Later on, define a new derived type by extending the abstract object:

type, extends(eqObject_abs) :: stringEQ
  character(:), allocatable :: chars
contains
  procedure :: eq_object => eq_object_StringEq
end type

Finally, declare its deferred type:

logical function eq_object_stringEq(self, other)
  !< true if self and other are the same type and contains the same chars
  class(stringEq), intent(in) :: self
  class(eqObject_abs), intent(in) :: other

  class(stringEq), pointer :: pstringEq

  select type(obj => other) !< cast type
  type is (stringEq)
      pStringEq => obj
  class default
      ! error (or false), different types
      write(*,*) "Unexpected type found"
      stop 1
  end select
    
  eq_object_stringEq = (self % chars == pStringEq % chars)
end function eq_object_stringEq

Regarding the abstract interface, the self argument must be adapted according to the new class where it belongs (stringEq vs eqObject_abs).

Its implementation is not obvious and it requires a certain degree of knowledge about Fortran.

Leave a Reply

Your email address will not be published. Required fields are marked *