2

是否可以用非多态过程重载延迟过程?

我想创建一个Parent带有过程 ( foo) 的抽象类 (),它必须由扩展的每个类重载Parent。当我想再次扩展时遇到了问题,例如一个类 ( Grandchild) 扩展了一个扩展的类 ( Child) Parent

由于 Child 不是抽象的,它的 foo( foo_Child) 必须是多态的。而是Grandchild继承foo_Child,而不是被迫定义foo_Grandchild。此外,由于我不想foo_Child成为多态,我希望能够Childfoo_Child.

module test_module

  type, abstract :: Parent
  contains
    procedure(foo_Parent), deferred :: foo
  end type

  abstract interface
    subroutine foo_Parent(this,input)
      import Parent
      class(Parent), intent(out) :: this
      character(*),  intent(in)  :: input
    end subroutine
  end interface

  type, extends(Parent) :: Child
  contains
    procedure :: foo => foo_Child
  end type

  type, extends(Child) :: Grandchild
    ! Is not required to define foo=>foo_Grandchild.
    ! This is not the behaviour I want.
  end type

  interface Child
    module procedure new_Child
  end interface
contains

function new_Child(input) result(this)
  character(*), intent(in) :: input
  type(Child)              :: this
end function

subroutine foo_Child(this,input)
  type(Child),  intent(out) :: this ! Fails: 'this' is not polymorphic.
  character(*), intent(in)  :: input

  this = Child(input) ! Fails if type(Child) is replaced by class(Child).
end subroutine
end module

program test
  use test_module
end program

总结一下:

有什么方法可以使foo_Child非多态但也超载foo_Parent?或者有没有办法在多态过程中调用非多态函数(至少Child=Child分配非多态rhs)?如果没有,是否有解决方法?

(我不想定义class(Child)=type(Child),但如果它是唯一的选择)。

4

1 回答 1

3

对应于过程绑定的传递对象的虚拟参数必须始终是多态的。

内在赋值语言的规则不允许赋值给不可分配的多态对象。这是因为通常这样的分配将是类似于切片的错误 - 您将取消定义在 rhs 的动态类型中声明但未在 lhs 的声明类型中声明的对象的位。

可以使用 SELECT TYPE 和匹配对象动态类型的类型保护将多态对象向下转换为非多态对象。您还可以通过参数关联愉快地切入您的内心 - 多态实际参数可以与相同声明类型的非多态虚拟对象相关联。

通过使父类型抽象并延迟(或离开)绑定(正如您已经完成的那样),可以强制扩展实现绑定。在您的情况下,可能需要您的层次结构中的其他类型。

Parent (abstract) --> Child (abstract) +-> RealChild (concrete)
                                       |-> GrandChild (concrete)

Child上面可能只是将 foo 绑定延迟,或者它可以为该绑定提供一个过程,然后引入一个新的延迟绑定,RealChild并且GrandChild需要实现。

于 2018-05-03T16:26:19.783 回答