Fortran Coder

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

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

[复制链接]

127

帖子

35

主题

1

精华

大师

F 币
1153 元
贡献
592 点
跳转到指定楼层
楼主
发表于 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语句
子类模块可以导入父类模块相关内容  从而减少代码量
为何子类模块必须要把父类模块的抽象接口代码重写一遍呢?
分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

127

帖子

35

主题

1

精华

大师

F 币
1153 元
贡献
592 点
沙发
 楼主| 发表于 2019-7-19 10:45:55 | 显示全部楼层
vvt 发表于 2019-7-18 22:03
module super_class
中添加
public :: sub

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

127

帖子

35

主题

1

精华

大师

F 币
1153 元
贡献
592 点
板凳
 楼主| 发表于 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

127

帖子

35

主题

1

精华

大师

F 币
1153 元
贡献
592 点
地板
 楼主| 发表于 2019-8-3 17:13:42 | 显示全部楼层
lookbook 发表于 2019-8-3 12:32
个人感觉和重载没有关系,关键在于这是两个文件,而且有private属性,那么sub的定义只在super_class内有 ...

若子类成员方法的形参为父类的抽象接口,则父类模块需将其抽象接口公开
若子类模块没有使用父类的抽象接口,则父类模块不必将其抽象接口公开
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

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

GMT+8, 2024-5-4 11:07

Powered by Tencent X3.4

© 2013-2024 Tencent

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