Fortran Coder

查看: 11055|回复: 7
打印 上一主题 下一主题

[讨论] 子类模块为何不能重用父类模块的抽象接口?

[复制链接]

147

帖子

42

主题

1

精华

宗师

F 币
1297 元
贡献
630 点
跳转到指定楼层
楼主
发表于 2019-7-18 21:08:11 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
以下代码可以正常编译运行
[Fortran] 纯文本查看 复制代码
module super_class !父类
    implicit none
    private
    
    type,public::point
        real::x=0.0
        real::y=0.0
        procedure(sub),pointer::p=>null() !过程指针作为成员变量
    contains
        procedure,pass::point_new !父类构造函数
        procedure,pass::printSum  !打印成员变量之和
    end type point
 
    abstract interface !抽象接口
        subroutine sub(me,x,f)
            import::point !导入宿主定义
            class(point),intent(inout)::me
            real,dimension(:), intent(in)::x
            real,intent(out)             ::f
        end subroutine sub
    end interface
contains
    subroutine point_new(me,x,y) !父类构造函数
        class(point),intent(inout)::me
        real,intent(in)::x
        real,intent(in)::y
            
        me%x=x
        me%y=y
    end subroutine point_new
    
    subroutine printSum(me,pp) 
        class(point),intent(inout)::me
        procedure(sub)::pp !任何与子例程sub形参列表相同的子例程都能传入
        real::f
        
        me%p=>pp !过程指针确定指向
        call me%p([me%x,me%y],f) !相当于call me%pp()
        write(*,*)'父类sum=',f
    end subroutine printSum
end module super_class

module sub_class !子类
    use super_class
    implicit none
    private
    
    type,public,extends(point)::point3d
        real::z=0.0
    contains
        procedure,pass::point3d_new !子类构造函数
        procedure,pass::printSum !打印成员变量之和 子类重写覆盖
    end type point3d
    
    abstract interface !抽象接口
        subroutine sub(me,x,f)
            import::point !导入宿主定义
            class(point),intent(inout)::me
            real,dimension(:), intent(in)::x
            real,intent(out)             ::f
        end subroutine sub
    end interface 
contains
    subroutine point3d_new(me,x,y,z) !子类构造函数
        class(point3d),intent(inout)::me
        real,intent(in)::x
        real,intent(in)::y
        real,intent(in)::z
            
        call me%point%point_new(x,y) !调用父类的构造函数
        me%z=z
    end subroutine point3d_new
    
    subroutine printSum(me,pp) !子类重写覆盖
        class(point3d),intent(inout)::me
        procedure(sub)::pp !任何与子例程sub形参列表相同的子例程都能传入
        real::f
        
        me%p=>pp !过程指针确定指向
        call me%p([me%x,me%y,me%z],f) !相当于call me%pp()
        write(*,*)'子类sum=',f
    end subroutine printSum
end module sub_class

program main !主程序
    use super_class
    use sub_class
    implicit none
    
    type(point)::a
    type(point3d)::b
    
    call a%point_new(1.0,1.0)
    call a%printSum(sss)

    call b%point3d_new(2.0,2.0,2.0)
    call b%printSum(sss)
contains    
    subroutine sss(me,x,f) !抽象接口具体实现
        class(point),intent(inout)::me
        real,dimension(:), intent(in)::x
        real,intent(out)             ::f
        
        f=sum(x)
    end subroutine sss
end program main


但是将子类模块中的抽象接口相关语句注释后
编译将报错
按理说通过use语句
子类模块可以导入父类模块相关内容  从而减少代码量
为何子类模块必须要把父类模块的抽象接口代码重写一遍呢?
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

147

帖子

42

主题

1

精华

宗师

F 币
1297 元
贡献
630 点
8#
 楼主| 发表于 2019-8-3 17:13:42 | 只看该作者
lookbook 发表于 2019-8-3 12:32
个人感觉和重载没有关系,关键在于这是两个文件,而且有private属性,那么sub的定义只在super_class内有 ...

若子类成员方法的形参为父类的抽象接口,则父类模块需将其抽象接口公开
若子类模块没有使用父类的抽象接口,则父类模块不必将其抽象接口公开

79

帖子

17

主题

0

精华

专家

齊天大聖

F 币
433 元
贡献
266 点
7#
发表于 2019-8-3 12:32:27 | 只看该作者
weixing1531 发表于 2019-8-2 21:25
你的接口是静态方法,子类没有重写父类方法
我的接口是实例方法,子类重写了父类方法,抽象接口作为实例方 ...

个人感觉和重载没有关系,关键在于这是两个文件,而且有private属性,那么sub的定义只在super_class内有效。sub_class模块里的过程printsum是不知道pp的原型是什么的。你可以在sub_class内,把sub的名字改成其他,一样能通过。

147

帖子

42

主题

1

精华

宗师

F 币
1297 元
贡献
630 点
6#
 楼主| 发表于 2019-8-2 21:25:40 | 只看该作者
本帖最后由 weixing1531 于 2019-8-2 22:17 编辑
lookbook 发表于 2019-8-2 15:42
我重现了一下,其实代码上的问题,个人感觉不在类的继承上。而在于printSum上。

module m_father

你的接口是静态方法,子类没有重写父类方法
我的接口是实例方法,子类重写了父类方法,抽象接口作为实例方法形参
可能区别就在这
我的代码假如不重写父类方法也可以不用公开抽象接口

[Fortran] 纯文本查看 复制代码
module super_class !父类
    implicit none
    private
    
    type,public::point
        real::x=0.0
        real::y=0.0
        procedure(sub),pointer::p=>null() !过程指针作为成员变量
    contains
        procedure,pass::point_new !父类构造函数
        procedure,pass::printSum  !打印成员变量之和
    end type point
 
    abstract interface !抽象接口
        subroutine sub(me,x,f)
            import::point !导入宿主定义
            class(point),intent(inout)::me
            real,dimension(:), intent(in)::x
            real,intent(out)             ::f
        end subroutine sub
    end interface
contains
    subroutine point_new(me,x,y) !父类构造函数
        class(point),intent(inout)::me
        real,intent(in)::x
        real,intent(in)::y
            
        me%x=x
        me%y=y
    end subroutine point_new
    
    subroutine printSum(me,pp) 
        class(point),intent(inout)::me
        procedure(sub)::pp !任何与子例程sub形参列表相同的子例程都能传入
        real::f
        
        me%p=>pp !过程指针确定指向
        call me%p([me%x,me%y],f) !相当于call me%pp()
        write(*,*)'父类sum=',f
    end subroutine printSum
end module super_class

module sub_class !子类
    use super_class
    implicit none
    private
    
    type,public,extends(point)::point3d
        real::z=0.0
    contains
        procedure,pass::point3d_new !子类构造函数
    end type point3d
contains
    subroutine point3d_new(me,x,y,z) !子类构造函数
        class(point3d),intent(inout)::me
        real,intent(in)::x
        real,intent(in)::y
        real,intent(in)::z
            
        call me%point%point_new(x,y) !调用父类的构造函数
        me%z=z
    end subroutine point3d_new

end module sub_class

program main !主程序
    use super_class
    use sub_class
    implicit none
    
    type(point)::a
    type(point3d)::b
    
    call a%point_new(1.0,1.0)
    call a%printSum(sss)

    call b%point3d_new(2.0,2.0,2.0)
    call b%printSum(sss)
contains    
    subroutine sss(me,x,f) !抽象接口具体实现
        class(point),intent(inout)::me
        real,dimension(:), intent(in)::x
        real,intent(out)             ::f
        
        f=sum(x)
    end subroutine sss
end program main

79

帖子

17

主题

0

精华

专家

齊天大聖

F 币
433 元
贡献
266 点
5#
发表于 2019-8-2 15:42:56 | 只看该作者
我重现了一下,其实代码上的问题,个人感觉不在类的继承上。而在于printSum上。

module m_father
  implicit none
  private
  type,public :: t_father
     procedure(temp),nopass,pointer :: p
  end type t_father

  abstract interface
     function temp(a) result(out)
       implicit none
       integer,intent(in) :: a
       integer :: out
     end function temp
  end interface
end module m_father

module m_son
  use m_father
  implicit none
  private

  type,extends(t_father),public :: t_son
     integer :: a
  end type t_son
end module m_son

program main
  use m_son
  implicit none

  type(t_son) :: one
  one%p=>jiecheng
  print*,one%p(5)

contains
  function jiecheng(a) result(out)
    implicit none
    integer,intent(in) :: a
    integer :: out

    integer :: i

    out=1
    do i=2,a
       out=out*a
    end do
  end function jiecheng
end program main

我测试了,这样是没有问题的

79

帖子

17

主题

0

精华

专家

齊天大聖

F 币
433 元
贡献
266 点
地板
发表于 2019-7-29 22:27:09 | 只看该作者
赞,mark 码一下

147

帖子

42

主题

1

精华

宗师

F 币
1297 元
贡献
630 点
板凳
 楼主| 发表于 2019-7-19 10:45:55 | 只看该作者
vvt 发表于 2019-7-18 22:03
module super_class
中添加
public :: sub

原来是这样
一直纳闷抽象接口怎么没有接口名

954

帖子

0

主题

0

精华

大师

F 币
184 元
贡献
75 点

规矩勋章元老勋章新人勋章水王勋章热心勋章

QQ
沙发
发表于 2019-7-18 22:03:46 | 只看该作者
module super_class
中添加
public :: sub
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-12-29 00:00

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表