next up previous contents
Next: Recursive Subprograms Up: Examples and Exercises Previous: Modules

Interfaces and Generic Subprograms

Interfaces refer to how much knowledge the compiler has about an procedure during compilation. If the interface is explicit, then the compiler can verify that the subprogram is being called correctly. If, however, the interface is implicit, then the Fortran 90 compiler has no information about the types and number of the subprogram's arguments or the return value of the result for a function. (Implicit typing is used in the calling program to determine the return result of a function if no declaration is given.) Consequently, no type-checking can be done to verify that a subprogram has been called correctly. Implicit interfaces are all that are available in Fortran 77.

Subprograms such as module procedures and internal functions have an explicit interface by default, and no explicit interface block is necessary. External subprograms have an implicit interface by default, and an interface block is necessary to specify an explicit interface of an external subprogram; as mentioned above, this allows type-checking of actual and formal arguments in a reference to a subprogram. Examples of interface blocks for two external functions, f and g, are given below.

interface
   function f( x )
      real f
      real, intent( in ) :: x
   end function f
   function g( y )
      integer g
      integer, intent( in ) :: y
   end function g
end interface

Interfaces are also necessary to define a generic subprogram. Generic subprograms should be familiar from Fortran 77 intrinsics such as sin or operators such as `+'. These intrinsic functions were special cases in Fortran 77 and were overloaded to work on a variety of argument types-- sin( x ) will properly compute the sine of its argument, whether x is single or double precision, real or complex. In Fortran 90, user-defined subprograms can be generic in the same sense. Generic functions and subroutines may be defined, similar to any other subprogram, although the interface must be explicit. The usual way to define such a generic function is to place it in a module as in the example below.

module RationalArithmetic
   type rational
      integer n, d   ! Numerator and denominator.
   end type rational

   interface operator (*)
      module procedure integerRationalMultiply, &
                       rationalIntegerMultiply
   end interface

   contains

   function integerRationalMultiply( i, r )
      type( rational ) integerRationalMultiply
      integer, intent( in ) :: i
      type( rational ), intent( in ) :: r

      integerRationalMultiply = rational( i * r%n, r%d )
   end function integerRationalMultiply

   function rationalIntegerMultiply( r, i )
      type( rational ) rationalIntegerMultiply
      type( rational ), intent( in ) :: r
      integer, intent( in ) :: i

      rationalIntegerMultiply = rational( i * r%n, r%d )
   end function rationalIntegerMultiply

end module RationalArithmetic

This use of operators on derived types is a much more natural form of expression for many mathematical objects that can be modeled with user-defined types. The overloading of function names and operators is handled completely by the compiler. A reference to the `+' operator in the example above causes the compiler to insert a call to the appropriate function based on the types of arguments in the particular call. This function substitution can be completely determined at compile time and incurs no run-time overhead.

exercise230


next up previous contents
Next: Recursive Subprograms Up: Examples and Exercises Previous: Modules