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:
- 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? - 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
Post a Comment