2014-03-05 62 views
1

我還沒有在Fortran中找到有關泛型的信息。具有任意類型值的節點類,Fortran 2003

我想創建一個節點類:

  1. 包含任意類的變量,「任何::值,」
  2. 其中可指定的類或者(a)在實例化或者(b)通過init子例程。

理想情況下,我想模仿的Java功能:

Node<Integer> n = new Node<Integer>(); 

這是可能在2003年的Fortran?或者,我將不得不爲每個可能具有「價值」的類創建一個節點派生類?

第一篇文章中提出的解決方案並不完全符合我的要求。試想一下:

program generics_test 

implicit none 

type node_int 
    integer :: x 
end type node_int 

type node 
    class(*), allocatable :: value 
end type node 

type(node) :: obj 

allocate(node_int :: obj%value) 

!This must be used: 
select type (val => obj%value) 
    type is (node_int) 
    val%x = 1 
    class default 
    !throw en error 
end select 


end program generics_test 

這說明了一個主要問題:需要select type與分配的無限多態對象進行交互。舉個例子:

module node_class 

    type node 
    class(*), allocatable :: anything 

    contains 
     procedure, public :: init => init_sub 
    end type node 

    private :: init_sub 

    contains 

    subroutine init_sub(this, something) 
     class(node)   :: this 
     somethingObj  :: something ! <--- this assumes we know what soemthing is; 
             ! generous, since my question doesn't assume that 
     allocate(this%anything, source=something) 
    end subroutine init_sub 

end module node_class 

看來,雖然你可能需要class(*), allocatable :: anythingallocate(anythingObj, source=somethingObj)某處type node內,node不能永遠治療anything,就好像是一個somethingObj除非anything出現在select type... type is (somethingObj)塊。因此,爲了模擬我寫過的select type以上的Java代碼片段,每個對象都必須有一個case,它會遇到

+0

你必須使用'select type'塊來處理a定位類型的無限多態。 –

+0

你能編輯上面的程序來證明這一點嗎?更重要的是,這不需要你知道你正在檢查的類型嗎? –

+0

是的,當然它需要它,但是如果你指定了某個東西,你必須知道它是什麼類型! –

回答

2

有可能有一個組件無限多態實體

type node_int 
end type node_int 

type node 
    class(*), allocatable :: value 
end type node 

type(node) obj 

allocate(node_int :: obj%value) 

end 

這裏,class(*)是你的「一切」(甚至,由於@IanH指正,固有類型)和allocate語句設置的類型。

這是可能的,如果你想獲得更接近Java的岬覆蓋結構構造,使

obj = node(mold) 

作品,其中動態類型從mold拍攝。 [Fortran 2008在allocate中有mold=說明符。]但除非有要求,否則我不會進入該說明。

取決於你想要做什麼,你可能會發現這種方法比具有不同類型的工作要多得多。

編輯,以下問題更新

當一個人再願意使用無限多態實體的價值上面給出的,一種是誘惑的東西像

allocate (integer :: obj%value) 
obj%value = 1 

這將無法正常工作沒有Fortran 2008自動分配規則。 [在這個問題一個具有node_int的x組成部分,但我只是假裝node_int本身就是一個integer]

相反,人們可以使用源分配:

allocate (obj%value, source=1) 

select type構建

select type (x => obj%value) 
type is(integer) 
    x = 1 
end select 

[這是我的建議,這是一個很多工作的心臟。]

的更詳細的例子,其中包括源分配和構造從上面

module types 

    type Penguin 
    character(len=20) :: name 
    end type Penguin 

    type node 
    class(*), allocatable :: value 
    end type node 

    interface node 
    module procedure node_c 
    end interface node 

contains 

    function node_c(value) 
    class(*), intent(in) :: value 
    type(node) node_c 

    allocate(node_c%value, source=value) 
    end function node_c 

end module types 

program test 

    use types 
    type(node) obj(3) 

    allocate(obj(1)%value, source = 1) 
    allocate(obj(2)%value, source = Penguin('Percy')) 
    obj(3) = node(Penguin('Harold')) 

    do i=1, 3 
    select type (val => obj(i)%value) 
    type is (integer) 
     print '("Value is an integer: ", I0)', val 
    class is (Penguin) 
     print '("Value is a penguin called ", A)', TRIM(val%name) 
    end select 
    end do 

end 

輸出,與ifort編譯14.0.1

值是一個整數:1個
值是一個企鵝稱爲珀西
價值是一隻名叫哈羅德的企鵝

+0

你是什麼意思「類(*)不包括內在類型,如整數」? – IanH

+0

@francescalus你能解釋一下如何重寫結構構造函數嗎? – bdforbes

+1

只需使用一個名爲'node'的接口塊和一個返回結構的函數即可。 –