实际上你可以使用这种方法开箱即用(但不是向下投射)开箱即用:
PROGRAM main
IMPLICIT NONE
TYPE :: parent
INTEGER :: a
END TYPE parent
TYPE, EXTENDS(parent) :: child
INTEGER :: b
END TYPE child
CLASS(parent), ALLOCATABLE :: p
TYPE(child) :: c
ALLOCATE (p)
p%a = 5
c%a = 10
c%b = 15
PRINT *, p%a
! p = c
DEALLOCATE (p)
ALLOCATE (p, source=c)
PRINT *, p%a
DEALLOCATE (p)
END PROGRAM main
Run Code Online (Sandbox Code Playgroud)
注意:
或者,您可以定义从子类型到父级的分配:
MODULE types
IMPLICIT NONE
TYPE :: parent
INTEGER :: a
CONTAINS
PROCEDURE, PRIVATE :: parent_from_child
GENERIC :: ASSIGNMENT(=) => parent_from_child
END TYPE parent
TYPE, EXTENDS(parent) :: child
INTEGER :: b
END TYPE child
CONTAINS
SUBROUTINE parent_from_child(this, c)
CLASS(parent), INTENT(INOUT) :: this
CLASS(child), INTENT(IN) :: c
this%a = c%a
END SUBROUTINE parent_from_child
END MODULE types
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您不需要使用多态实体和特殊形式的ALLOCATABLE语句:
PROGRAM main
USE types
IMPLICIT NONE
TYPE(parent) :: p
TYPE(child) :: c
p%a = 5
c%a = 10
c%b = 15
PRINT *, p%a
p = c
PRINT *, p%a
END PROGRAM main
Run Code Online (Sandbox Code Playgroud)
沮丧...嗯...这是不安全的,它违背了强大的打字纪律.当我面对挫折时,我试图以相同的方式思考 - 使用相同的方法.您需要定义另一个任务 - 从父级到子级.唯一的问题是如果你将使用完全相同的方案(GENERIC绑定),child_from_parent将无法与parent_from_child区分开.但是你可以用另一种方式做到这一点:
MODULE types
IMPLICIT NONE
INTERFACE ASSIGNMENT(=)
MODULE PROCEDURE parent_from_child, child_from_parent
END INTERFACE
TYPE :: parent
INTEGER :: a
END TYPE parent
TYPE, EXTENDS(parent) :: child
INTEGER :: b
END TYPE child
CONTAINS
SUBROUTINE parent_from_child(this, c)
TYPE(parent), INTENT(INOUT) :: this
CLASS(child), INTENT(IN) :: c
this%a = c%a
END SUBROUTINE parent_from_child
SUBROUTINE child_from_parent(this, p)
TYPE(child), INTENT(INOUT) :: this
CLASS(parent), INTENT(IN) :: p
this%a = p%a
this%b = 0
END SUBROUTINE child_from_parent
END MODULE types
PROGRAM main
USE types
IMPLICIT NONE
CLASS(parent), ALLOCATABLE :: p
TYPE(child) :: c
c%a = 10
c%b = 15
ALLOCATE (p, source=c)
c%a = 5
PRINT *, c%a
c = p
PRINT *, c%a
END PROGRAM main
Run Code Online (Sandbox Code Playgroud)
但这不是一个降级.向下转换是将对基类的引用转换为其派生类之一.您需要检查引用对象的类型是否确实是要转换的对象的类型或它的派生类型,因此如果不是这样,则发出错误.
星期五晚上...做Fortran的好时机.=)最后我最终得到:
MODULE types
IMPLICIT NONE
TYPE :: parent
INTEGER :: a
END TYPE parent
TYPE, EXTENDS(parent) :: child
INTEGER :: b
END TYPE child
CONTAINS
SUBROUTINE cast(from, to)
CLASS(parent), INTENT(IN) :: from
CLASS(parent), INTENT(INOUT) :: to
SELECT TYPE (to)
TYPE IS (parent)
SELECT TYPE (from)
TYPE IS (parent)
PRINT *, "ordinary assignment"
to = from
TYPE IS (child)
PRINT *, "up-casting"
to%a = from%a
END SELECT
TYPE IS (child)
SELECT TYPE (from)
TYPE IS (parent)
PRINT *, "No way!"
TYPE IS (child)
PRINT *, "down-casting"
to = from
END SELECT
END SELECT
END SUBROUTINE cast
END MODULE types
PROGRAM main
USE types
IMPLICIT NONE
CLASS(parent), ALLOCATABLE :: p1, p2
TYPE(child) :: c1, c2
ALLOCATE (p1, p2)
p1%a = 1
p2%a = 2
c1%a = 1
c1%b = 1
c2%a = 2
c2%b = 2
PRINT *, p1%a
! up-casting from c2 to p1
CALL cast(c2, p1)
PRINT *, p1%a
PRINT *, "----------"
DEALLOCATE (p2)
ALLOCATE (p2, source=c1)
PRINT *, c2%a, c2%b
! down-casting from p2 to c2
CALL cast(p2, c2)
PRINT *, c2%a, c2%b
DEALLOCATE (p1, p2)
END PROGRAM main
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1570 次 |
| 最近记录: |