【发布时间】:2015-08-29 16:26:03
【问题描述】:
考虑一个经典的 OOP 示例(参见文章末尾的源代码):
- 抽象基类 Shape
- 类 Rectangle 扩展 Shape
问题:
- 在下面的源代码中,我尝试使用
class(Shape), pointer :: this为抽象类Shape 定义一个构造函数,结果从未分配指针。这是在 Fortran 中为抽象类定义构造函数的正确方法吗? - 如何在扩展类(Rectangle)的构造函数中调用基类(Shape)的构造函数?
示例源代码
更新了来自Ed Smith 的建议,该建议适用于非抽象基类。
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
这个程序给出以下输出:
Constructing rectangle
Rectangle with center point 6.9194863361077724E-310 6.9194863361077724E-310 has area 12.000000000000000
由于尚未调用基类构造函数,因此 centerPoint 变量未初始化。在这个简单的示例中,可以从 Rectangle 构造函数手动初始化变量,但对于更复杂的情况,这可能会导致大量代码重复。
【问题讨论】: