Fortran Coder

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

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

[复制链接]

156

帖子

45

主题

1

精华

宗师

F 币
1368 元
贡献
649 点
跳转到指定楼层
楼主
发表于 2019-7-18 21:08:11 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
以下代码可以正常编译运行
[Fortran] 纯文本查看 复制代码
001module super_class !父类
002    implicit none
003    private
004     
005    type,public::point
006        real::x=0.0
007        real::y=0.0
008        procedure(sub),pointer::p=>null() !过程指针作为成员变量
009    contains
010        procedure,pass::point_new !父类构造函数
011        procedure,pass::printSum  !打印成员变量之和
012    end type point
013  
014    abstract interface !抽象接口
015        subroutine sub(me,x,f)
016            import::point !导入宿主定义
017            class(point),intent(inout)::me
018            real,dimension(:), intent(in)::x
019            real,intent(out)             ::f
020        end subroutine sub
021    end interface
022contains
023    subroutine point_new(me,x,y) !父类构造函数
024        class(point),intent(inout)::me
025        real,intent(in)::x
026        real,intent(in)::y
027             
028        me%x=x
029        me%y=y
030    end subroutine point_new
031     
032    subroutine printSum(me,pp)
033        class(point),intent(inout)::me
034        procedure(sub)::pp !任何与子例程sub形参列表相同的子例程都能传入
035        real::f
036         
037        me%p=>pp !过程指针确定指向
038        call me%p([me%x,me%y],f) !相当于call me%pp()
039        write(*,*)'父类sum=',f
040    end subroutine printSum
041end module super_class
042 
043module sub_class !子类
044    use super_class
045    implicit none
046    private
047     
048    type,public,extends(point)::point3d
049        real::z=0.0
050    contains
051        procedure,pass::point3d_new !子类构造函数
052        procedure,pass::printSum !打印成员变量之和 子类重写覆盖
053    end type point3d
054     
055    abstract interface !抽象接口
056        subroutine sub(me,x,f)
057            import::point !导入宿主定义
058            class(point),intent(inout)::me
059            real,dimension(:), intent(in)::x
060            real,intent(out)             ::f
061        end subroutine sub
062    end interface
063contains
064    subroutine point3d_new(me,x,y,z) !子类构造函数
065        class(point3d),intent(inout)::me
066        real,intent(in)::x
067        real,intent(in)::y
068        real,intent(in)::z
069             
070        call me%point%point_new(x,y) !调用父类的构造函数
071        me%z=z
072    end subroutine point3d_new
073     
074    subroutine printSum(me,pp) !子类重写覆盖
075        class(point3d),intent(inout)::me
076        procedure(sub)::pp !任何与子例程sub形参列表相同的子例程都能传入
077        real::f
078         
079        me%p=>pp !过程指针确定指向
080        call me%p([me%x,me%y,me%z],f) !相当于call me%pp()
081        write(*,*)'子类sum=',f
082    end subroutine printSum
083end module sub_class
084 
085program main !主程序
086    use super_class
087    use sub_class
088    implicit none
089     
090    type(point)::a
091    type(point3d)::b
092     
093    call a%point_new(1.0,1.0)
094    call a%printSum(sss)
095 
096    call b%point3d_new(2.0,2.0,2.0)
097    call b%printSum(sss)
098contains   
099    subroutine sss(me,x,f) !抽象接口具体实现
100        class(point),intent(inout)::me
101        real,dimension(:), intent(in)::x
102        real,intent(out)             ::f
103         
104        f=sum(x)
105    end subroutine sss
106end program main


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

156

帖子

45

主题

1

精华

宗师

F 币
1368 元
贡献
649 点
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的名字改成其他,一样能通过。

156

帖子

45

主题

1

精华

宗师

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

module m_father

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

[Fortran] 纯文本查看 复制代码
01module super_class !父类
02    implicit none
03    private
04     
05    type,public::point
06        real::x=0.0
07        real::y=0.0
08        procedure(sub),pointer::p=>null() !过程指针作为成员变量
09    contains
10        procedure,pass::point_new !父类构造函数
11        procedure,pass::printSum  !打印成员变量之和
12    end type point
13  
14    abstract interface !抽象接口
15        subroutine sub(me,x,f)
16            import::point !导入宿主定义
17            class(point),intent(inout)::me
18            real,dimension(:), intent(in)::x
19            real,intent(out)             ::f
20        end subroutine sub
21    end interface
22contains
23    subroutine point_new(me,x,y) !父类构造函数
24        class(point),intent(inout)::me
25        real,intent(in)::x
26        real,intent(in)::y
27             
28        me%x=x
29        me%y=y
30    end subroutine point_new
31     
32    subroutine printSum(me,pp)
33        class(point),intent(inout)::me
34        procedure(sub)::pp !任何与子例程sub形参列表相同的子例程都能传入
35        real::f
36         
37        me%p=>pp !过程指针确定指向
38        call me%p([me%x,me%y],f) !相当于call me%pp()
39        write(*,*)'父类sum=',f
40    end subroutine printSum
41end module super_class
42 
43module sub_class !子类
44    use super_class
45    implicit none
46    private
47     
48    type,public,extends(point)::point3d
49        real::z=0.0
50    contains
51        procedure,pass::point3d_new !子类构造函数
52    end type point3d
53contains
54    subroutine point3d_new(me,x,y,z) !子类构造函数
55        class(point3d),intent(inout)::me
56        real,intent(in)::x
57        real,intent(in)::y
58        real,intent(in)::z
59             
60        call me%point%point_new(x,y) !调用父类的构造函数
61        me%z=z
62    end subroutine point3d_new
63 
64end module sub_class
65 
66program main !主程序
67    use super_class
68    use sub_class
69    implicit none
70     
71    type(point)::a
72    type(point3d)::b
73     
74    call a%point_new(1.0,1.0)
75    call a%printSum(sss)
76 
77    call b%point3d_new(2.0,2.0,2.0)
78    call b%printSum(sss)
79contains   
80    subroutine sss(me,x,f) !抽象接口具体实现
81        class(point),intent(inout)::me
82        real,dimension(:), intent(in)::x
83        real,intent(out)             ::f
84         
85        f=sum(x)
86    end subroutine sss
87end 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 码一下

156

帖子

45

主题

1

精华

宗师

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

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

955

帖子

0

主题

0

精华

大师

F 币
188 元
贡献
77 点

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

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

本版积分规则

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

GMT+8, 2025-5-3 16:17

Powered by Discuz! X3.4

© 2013-2025 Comsenz Inc.

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