Consider one of the classic OOP examples (see source code at the end of the post):
- Abstract base class Shape
- Class Rectangle extending Shape
Questions:
- In the source code below I've tried to define a constructor for the abstract class Shape using class(Shape), pointer :: thisas result without ever allocating the pointer. Is this the correct way of defining a constructor for an abstract class in Fortran?
- How can I invoke the constructor of the base class (Shape) in the constructor of the extending class (Rectangle)?
Example Source Code
Updated with suggestion from Ed Smith which works for non-abstract base classes.
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
This program gives the following output:
 Constructing rectangle
 Rectangle with center point   6.9194863361077724E-310   6.9194863361077724E-310  has area    12.000000000000000 
Since the base class constructor haven't been invoked the centerPoint variable isn't initalized. In this simple example the variable could be initialized manually from the Rectangle constructor, but for more complex cases this might lead to significant duplication of code.
 
     
     
    