oop - Invoking constructor of abstract base class in Fortran -


consider 1 of classic oop examples (see source code @ end of post):

  • abstract base class shape
  • class rectangle extending shape

questions:

  1. in source code below i've tried define constructor abstract class shape using class(shape), pointer :: this result without ever allocating pointer. correct way of defining constructor abstract class in fortran?
  2. how can invoke constructor of base class (shape) in constructor of extending class (rectangle)?

example source code

updated suggestion ed smith works 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) ::             double precision :: area         end function getarea     end interface   contains      !correct way of defining constructor abstract class?     function constructor(xcenter, ycenter) result(this)            class(shape), pointer ::         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) ::         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 ::         double precision :: length         double precision :: width         double precision :: xcenter         double precision :: ycenter          print *, "constructing rectangle"          allocate(this)         this%length = length         this%width = width         !how invoke base class constructor here?         !the line below works non-abstract base classes          !constructor result can type(shape)         this%shape = shape(xcenter, ycenter)      end function constructor      function getarea(this) result(area)         class(rectangle), intent(in) ::         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 center point", r%getcenterpoint(), " has area ", r%getarea() end program main 

this program gives following output:

 constructing rectangle  rectangle center point   6.9194863361077724e-310   6.9194863361077724e-310  has area    12.000000000000000  

since base class constructor haven't been invoked centerpoint variable isn't initalized. in simple example variable initialized manually rectangle constructor, more complex cases might lead significant duplication of code.

this question , hope more experience of oop in fortran can give better answer. first question, shouldn't need pointer, instead can define constructor as,

type(shape) function constructor(xcenter, ycenter)         double precision, intent(in) :: xcenter     double precision, intent(in) :: ycenter      print *, "constructing base shape"     constructor%centerpoint = [xcenter, ycenter] end function constructor 

for second question, answer should call parent in rectangle constructor line constructor%shape = shape(xcenter, ycenter) in rectangle constructor function.

type(rectangle) function constructor(length, width, xcenter, ycenter)      type(rectangle), pointer ::     double precision, intent(in) :: xcenter     double precision, intent(in) :: ycenter     double precision, intent(in) :: length     double precision, intent(in) :: width      print *, "constructing rectangle"      !invoke base class constructor here     constructor%shape_ = shape(xcenter, ycenter)     constructor%length = length     constructor%width = width  end function constructor 

i cannot work intel compiler v13.0.1. returns error: if rightmost part-name of abstract type, data-ref shall polymorphic. understand it, fortran 2008 standard should allow call constructor of abstract type if parent of current type. may work in later compilers, check out this answer (and try case).

if not, minimal working solution of want, solution used have abstract shape class defines interface, , define constructor in fist object inherits this, here shape type (similar section 11.3.2 of this fortran oop example). solution follows,

module shape_mod      type, abstract :: abstractshape             integer :: color             logical :: filled             integer :: x             integer :: y     end type abstractshape     interface abstractshape         module procedure initshape     end interface abstractshape      type, extends (abstractshape) :: shape     end type shape      type, extends (shape) :: rectangle             integer :: length             integer :: width     end type rectangle      interface rectangle         module procedure initrectangle     end interface rectangle   contains      ! initialize shape objects     subroutine initshape(this, color, filled, x, y)          class(shape) ::         integer :: color         logical :: filled         integer :: x         integer :: y          this%color = color         this%filled = filled         this%x = x         this%y = y      end subroutine initshape      ! initialize rectangle objects     subroutine initrectangle(this, color, filled, x, y, length, width)          class(rectangle) ::         integer :: color         logical :: filled         integer :: x         integer :: y         integer, optional :: length           integer, optional :: width             this%shape = shape(color, filled, x, y)          if (present(length))            this%length = length         else            this%length = 0         endif         if (present(width))              this%width = width         else              this%width = 0         endif     end subroutine initrectangle  end module shape_mod  program test_oop     use shape_mod      implicit none      ! declare instance of rectangle     type(rectangle) :: rect       ! calls initrectangle      rect = rectangle(2, .false., 100, 200, 11, 22)        print*, rect%color, rect%filled, rect%x, rect%y, rect%length, rect%width   end program test_oop 

sorry, notation different example help...


Comments

Popular posts from this blog

c# - Validate object ID from GET to POST -

node.js - Custom Model Validator SailsJS -

php - Find a regex to take part of Email -