Interfaces in Co-array Fortran

Interfaces in Co-array Fortran are not a native language feature. However, we can simulate similar behavior using abstract types and type-bound procedures. Here’s an equivalent implementation:

module geometry_module
  use, intrinsic :: iso_fortran_env
  implicit none

  private
  public :: geometry, rect, circle, measure

  type, abstract :: geometry
  contains
    procedure(area_interface), deferred :: area
    procedure(perim_interface), deferred :: perim
  end type geometry

  abstract interface
    function area_interface(this) result(a)
      import geometry
      class(geometry), intent(in) :: this
      real :: a
    end function area_interface

    function perim_interface(this) result(p)
      import geometry
      class(geometry), intent(in) :: this
      real :: p
    end function perim_interface
  end interface

  type, extends(geometry) :: rect
    real :: width, height
  contains
    procedure :: area => rect_area
    procedure :: perim => rect_perim
  end type rect

  type, extends(geometry) :: circle
    real :: radius
  contains
    procedure :: area => circle_area
    procedure :: perim => circle_perim
  end type circle

contains

  function rect_area(this) result(a)
    class(rect), intent(in) :: this
    real :: a
    a = this%width * this%height
  end function rect_area

  function rect_perim(this) result(p)
    class(rect), intent(in) :: this
    real :: p
    p = 2 * this%width + 2 * this%height
  end function rect_perim

  function circle_area(this) result(a)
    class(circle), intent(in) :: this
    real :: a
    a = 3.14159265358979 * this%radius**2
  end function circle_area

  function circle_perim(this) result(p)
    class(circle), intent(in) :: this
    real :: p
    p = 2 * 3.14159265358979 * this%radius
  end function circle_perim

  subroutine measure(g)
    class(geometry), intent(in) :: g
    print *, "Area:", g%area()
    print *, "Perimeter:", g%perim()
  end subroutine measure

end module geometry_module

program main
  use geometry_module
  implicit none

  type(rect) :: r
  type(circle) :: c

  r = rect(width=3.0, height=4.0)
  c = circle(radius=5.0)

  call measure(r)
  call measure(c)

end program main

In this Co-array Fortran implementation:

  1. We define an abstract type geometry with deferred procedures area and perim. This acts similarly to an interface in other languages.

  2. We create concrete types rect and circle that extend geometry and implement the required procedures.

  3. The measure subroutine takes a geometry object and calls its area and perim methods, demonstrating polymorphism.

  4. In the main program, we create instances of rect and circle, then pass them to the measure subroutine.

To compile and run this program:

$ gfortran -o geometry geometry.f90
$ ./geometry

This will output the area and perimeter for both the rectangle and circle objects.

Note that Co-array Fortran doesn’t have a direct equivalent to Go’s interfaces, but this approach using abstract types and type-bound procedures provides similar functionality in terms of polymorphism and code reuse.