2015-06-22 48 views
1

下面給出的最小工作的例子,我想修改,以避免複製/粘貼的良好的面向對象設計,避免複製/粘貼使用Fortran

call func_some_calc1(par) 
call func_some_calc2(par) 

兩個main_func_problem1main_func_problem2呼叫。 理想情況下,我希望有一個功能main_func,其輸入參數的類型爲t_parameters_problem1t_parameters_problem2的行爲不同。我可以聲明它的par參數基類型爲class(t_parameters_base),但是根據實際的參數類型(使用select type)在該函數內部有一個開關在結構上並不好。

爲了解決這個我試圖創建t_parameters_base類型procedure,這是調用這些程序,來實現這樣的事情(C++語法):

class t_parameters_base { 
    virtual void main_func() { 
    func_some_calc1(this) 
    func_some_calc2(this) 
    } 
} 
class t_parameters_problem1: public t_parameters_base { 
    virtual void main_func() { 
    t_parameters_base::main_func(); 
    func_some_calc3_problem1(this); 
    } 
} 

但問題是,這些程序被使用這種類型的輸入參數會導致循環依賴。怎麼可能解決這個問題?

更新:請注意,我確實希望將func_some_calc1func_some_calc2的實現保留在不同的文件(模數/類)中,因爲它們使用類中的一些私有函數來實現非常不同的邏輯。

module parameters_base 
    type, public :: t_parameters_base 
    integer :: n 
    end type t_parameters_base 
end module parameters_base 

module parameters_problem1 
    use parameters_base 
    implicit none 

    type, extends(t_parameters_base), public :: t_parameters_problem1 
    integer :: p1 
    end type t_parameters_problem1 
end module parameters_problem1 

module parameters_problem2 
    use parameters_base 
    implicit none 

    type, extends(t_parameters_base), public :: t_parameters_problem2 
    integer :: p2 
    end type t_parameters_problem2 
end module parameters_problem2 

module some_calc1 
    use parameters_base 
    implicit none 
contains 
    subroutine func_some_calc1(par) 
    class(t_parameters_base) :: par 
    end subroutine func_some_calc1 
end module some_calc1 

module some_calc2 
    use parameters_base 
    implicit none 
contains 
    subroutine func_some_calc2(par) 
    class(t_parameters_base) :: par 
    end subroutine func_some_calc2 
end module some_calc2 

module some_calc3_problem1 
    use parameters_problem1 
    implicit none 
contains 
    subroutine func_some_calc3_problem1(par) 
    type(t_parameters_problem1) :: par 
    print*, par%p1 
    end subroutine func_some_calc3_problem1 
end module some_calc3_problem1 

module some_calc3_problem2 
    use parameters_problem2 
    implicit none 
contains 
    subroutine func_some_calc3_problem2(par) 
    type(t_parameters_problem2) :: par 
    print*, par%p2 
    end subroutine func_some_calc3_problem2 
end module some_calc3_problem2 

module main_problem1 
    use parameters_problem1 
    use some_calc1 
    use some_calc2 
    use some_calc3_problem1 
    implicit none 
contains 
    subroutine main_func_problem1(par) 
    type(t_parameters_problem1) :: par 

    call func_some_calc1(par) 
    call func_some_calc2(par) 
    call func_some_calc3_problem1(par) 
    end subroutine main_func_problem1 
end module main_problem1 

module main_problem2 
    use parameters_problem2 
    use some_calc1 
    use some_calc2 
    use some_calc3_problem2 
    implicit none 
contains 
    subroutine main_func_problem2(par) 
    type(t_parameters_problem2) :: par 

    call func_some_calc1(par) 
    call func_some_calc2(par) 
    call func_some_calc3_problem2(par) 
    end subroutine main_func_problem2 
end module main_problem2 

program module_test 
    use parameters_problem1 
    use parameters_problem2 
    use main_problem1 
    use main_problem2 

    implicit none 

    type(t_parameters_problem1) :: par1 
    type(t_parameters_problem2) :: par2 

    par1%p1 = 1 
    par2%p2 = 2 

    call main_func_problem1(par1) 
    call main_func_problem2(par2) 
end program module_test 
+0

爲什麼不用交換機創建一個例程。我建議你不要使用通用的'func_some_calc1,...',而是給出簡短的具體名稱,這樣一切都會更容易理解。 – Zeus

+0

你的意思是什麼開關?如果你的意思是聲明一個基類型的參數,然後在子例程內將它轉換爲實際傳遞的繼承類型,使用「select type」,那麼它不是一個好的體系結構。 – Vitaliy

+0

如何使用't_parameters'並單獨傳遞額外的一個。 – Zeus

回答

0

我認爲,你的目標是多態類型與類型綁定程序。下面你會找到一個工作的例子。爲了簡單起見,我沒有向類型添加任何數據,但當然,這可以輕鬆完成。例程invokeCalc12僅在基類型中定義,但可以從派生類型中調用,並且在Fortran中所有方法都是虛擬的,它將調用正確的方法。

module calc_base 
    implicit none 

    type, abstract :: CalcBase 
    contains 
    procedure(calcInterface), deferred :: calc1 
    procedure(calcInterface), deferred :: calc2 
    procedure :: invokeCalc12 
    end type CalcBase 

    interface 
    subroutine calcInterface(self, ii) 
     import :: CalcBase 
     class(CalcBase), intent(inout) :: self 
     integer, intent(in) :: ii 
    end subroutine calcInterface 
    end interface 

contains 

    subroutine invokeCalc12(self, ii) 
    class(CalcBase), intent(inout) :: self 
    integer, intent(in) :: ii 
    call self%calc1(ii) 
    call self%calc2(ii) 
    end subroutine invokeCalc12 

end module calc_base 


module some_calc 
    use calc_base 
    implicit none 

    type, extends(CalcBase) :: SomeCalc 
    contains 
    procedure :: calc1 
    procedure :: calc2 
    procedure :: calc3 
    end type SomeCalc 

contains 

    subroutine calc1(self, ii) 
    class(SomeCalc), intent(inout) :: self 
    integer, intent(in) :: ii 
    print *, "SomeCalc1:calc1", ii 
    end subroutine calc1 

    subroutine calc2(self, ii) 
    class(SomeCalc), intent(inout) :: self 
    integer, intent(in) :: ii 
    print *, "SomeCalc1:calc2", ii 
    end subroutine calc2 

    subroutine calc3(self, ii) 
    class(SomeCalc), intent(inout) :: self 
    integer, intent(in) :: ii 
    call self%%invokeCalc12(ii) 
    end subroutine calc3 

end module some_calc 


program test 
    use some_calc 
    implicit none 

    type(SomeCalc) :: mySimulation 

    call mySimulation%calc3(42) 

end program test 

注:我已經看到了類似的問題已經被張貼在comp.lang.fortran,但此刻我沒有找到工作的例子有,所以此留言。

+0

嗨巴林特,謝謝你的回答,我正在看。只是想說,我從來沒有在comp.lang.fortran上發佈我的問題,我很驚訝爲什麼有人會真的需要這樣做...... – Vitaliy

+0

@Vitaliy不知道爲什麼它出現在那裏。無論如何,我希望,上面的例子可以幫助您獲得正確的解決方案。 :-) –

+0

嗨Balint,在你的例子中,你將calc1()和calc2()的實現移到了擴展類中,而那些函數只使用基類參數,並且對於problem1和problem2表現相同。所以它看起來像你回答了一個不同的問題。除此之外,我想在不同的文件(模數/類)中實現calc1()和calc2(),因爲它們使用類中的一些私有函數來實現非常不同的邏輯,儘管我沒有在我的問題中明確提到 - 我會添加這個。 – Vitaliy