在 Java 中,任何从
Object
派生的类都有一个漂亮的函数:
public String toString()
它本身的功能不是很神奇,但是 Java 解释器使用它的方式使它非常有用。而且,当然,这不是生死攸关的事情,而是一件非常好的事情,让有些懒惰的编码人员的生活更轻松。据我所知,Fortran(或许多其他语言)中不存在任何类似的东西。
我错了吗?这样的东西存在吗?或者,在 Fortran 传说中是否隐藏着类似的东西?
对于那些不熟悉 Java 的人:简单(但有点不准确)说,如果在任何需要 String 的地方使用了一个对象变量(没有引用它的任何成员),Java 解释器会查找
toString()
变量类的
方法,通过层次结构默认向上(一直到 Object
)。因此,每个对象都有一些可用的toString()
。
在 Fortran 中将一个
toString()
函数实现到一个类(或类型)中并不是很麻烦。好吧,这有点取决于类型的复杂性,以及用户希望函数返回什么。
写起来会方便得多:
write(*,*) somevariable
代替
write(*,*) somevariable%toString()
与课程作业类似
character (len = *) :: str
str = somevariable
代替
str = somevariable%toString()
当然,这与类型转换有关。隐式类型转换,如果我没记错的话。
我不希望就此展开长时间的讨论,因为除了我已经写的内容,我没有什么可以贡献的了。
在 Fortran 中,变量从内部格式到字符串的转换是通过“Internal WRITE”完成的。例如:
character(100) :: str
write (str,*) somevariable
在派生类型变量的情况下,如果组件都是内部类型(或其他具有内部类型的派生类型),则组件将按顺序输出。如果您有任何指针或可分配组件,或者如果您对格式有特殊要求,您将声明一个“用户定义的派生类型 I/O 过程”来执行此操作,然后在 I/O 操作期间根据需要自动调用它.
你可能已经注意到,上面我声明变量
str
具有特定的长度,因为今天你需要这样做。将于今年晚些时候发布的 Fortran 2023 允许您将 str
声明为延迟长度可分配变量,内部写入将(重新)分配它到必要的长度。当然,您需要等待编译器实现该功能。
Fortran 没有“如果在预期 X 类型之一的地方给出 Y 类型的对象,则将其转换为 X 类型之一”的强烈概念。这涵盖了不同类型的数字对象(例如 Y 双精度、X 实数)以及派生类型和字符串。
您会在过程引用中的参数不匹配等情况下看到这一点。
在某些情况下我们确实有类型转换,比如在
x+y
中这两个对象是不同类型的。
所以,像
somevariable
这样的引用总是1对该对象的引用,而不是它的任何一个(或多个)组件或类型绑定过程/绑定名称。
在类似的地方
call dosomething(somevariable)
其中
dosomething
需要一个字符,但 somevariable
不是一个字符,永远不会为您执行隐式转换。
但是,在您感兴趣的两种情况下,可以说
somevariable
作为派生类型是预期的,但是会发生其他事情而不是立即处理该类型。
例如(具体解释见其他问答),我们可以定义一个类型
t
,它有一个通用的write(formatted)
和一个assignment(=)
的接口,它有一个字符左侧和type(t)
右侧边:
module mod
type t
integer :: i=0
contains
procedure :: write
generic :: write(formatted) => write
end type t
interface assignment(=)
module procedure assign
end interface assignment(=)
contains
subroutine write(dtv, unit, iotype, v_list, iostat, iomsg)
class(t), intent(in) :: dtv
integer, intent(in) :: unit
character(*), intent(in) :: iotype
integer, intent(in) :: v_list(:)
integer, intent(out) :: iostat
character(*), intent(inout) :: iomsg
write (unit, "(A)", iostat=iostat, iomsg=iomsg) "Object says hello"
end subroutine write
subroutine assign(lhs, rhs)
character(:), allocatable, intent(out) :: lhs
class(t), intent(in) :: rhs
lhs = "From assignment"
end subroutine assign
end module mod
可以使用
dt
编辑描述符(或使用列表定向输出)调用定义的输出过程,并且像往常一样定义赋值:
use mod, only : t, assignment(=)
character(:), allocatable :: str
print '(dt)', t()
str = t()
print '(A)', str
end
1 当这些组件都可以访问时,对派生类型对象的引用可以扩展到它的组件顺序在对象的内部数据传输中。