Quantcast
Channel: Intel® Fortran Compiler
Viewing all articles
Browse latest Browse all 3270

Invoking constructor of abstract base class in Fortran

$
0
0

I originally posted this question on Stackoverflow (http://stackoverflow.com/questions/30823756/invoking-constructor-of-abst...), but perhaps the Intel community har more knowledge on this topic?

Consider one of the classic OOP examples (see source code at the end of the post):

  • Abstract base class Shape
  • Class Rectangle extending Shape

I have two questions:

  1. In the source code below I've tried to define a constructor for the abstract class Shape using class(Shape), pointer :: this as result without ever allocating the pointer. Is this the correct way of defining a constructor for an abstract class in Fortran?
  2. How can I invoke the constructor of the base class (Shape) in the constructor of the extending class (Rectangle)? Using this%Shape = Shape(xCenter, yCenter) works for non-abstract base classes, but both the Intel compiler and gfortran gives me errors when the result type is class(Shape), pointer (required for an abstract class).
module Shape_mod
    implicit none

    private
    public Shape

    type, abstract :: Shape
        private
        double precision :: centerPoint(2)
    contains
        procedure :: getCenterPoint
        procedure(getArea), deferred :: getArea
    end type Shape

    interface Shape
        module procedure constructor
    end interface Shape

    abstract interface
        function getArea(this) result(area)
            import
            class(Shape), intent(in) :: this
            double precision :: area
        end function getArea
    end interface

contains

    !Correct way of defining a constructor for an abstract class?
    function constructor(xCenter, yCenter) result(this)
        class(Shape), pointer :: this
        double precision, intent(in) :: xCenter
        double precision, intent(in) :: yCenter

        print *, "constructing base shape"
        this%centerPoint = [xCenter, yCenter]
    end function constructor

    function getCenterPoint(this) result(point)
        class(Shape), intent(in) :: this
        double precision point(2)
        point = this%centerPoint
    end function getCenterPoint

end module Shape_mod

module Rectangle_mod
    use Shape_mod
    implicit none

    private
    public Rectangle

    type, extends(Shape) :: Rectangle
        private
        double precision :: length
        double precision :: width
    contains
        procedure :: getArea
    end type Rectangle


    interface Rectangle
        module procedure constructor
    end interface Rectangle

contains

    function constructor(length, width, xCenter, yCenter) result(this)
        type(Rectangle), pointer :: this
        double precision :: length
        double precision :: width
        double precision :: xCenter
        double precision :: yCenter

        print *, "Constructing rectangle"

        allocate(this)
        this%length = length
        this%width = width
        !How to invoke the base class constructor here?
        !The line below works for non-abstract base classes where the
        !constructor result can be type(Shape)
        this%Shape = Shape(xCenter, yCenter)
    end function constructor

    function getArea(this) result(area)
        class(Rectangle), intent(in) :: this
        double precision :: area

        area = this%length * this%width
    end function getArea

end module Rectangle_mod

program main
    use Rectangle_mod
    implicit none
    type(Rectangle) :: r

    r = Rectangle(4.0d0, 3.0d0, 0.0d0, 2.0d0)
    print *, "Rectangle with center point", r%getCenterPoint(), " has area ", r%getArea()
end program main

 


Viewing all articles
Browse latest Browse all 3270

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>