2010-11-23 17 views
14

Şu anda Fortran'daki yapı yapıcısını geçersiz kılmak mümkün mü? Ben (örneğin Fortran 2003 spec olduğu gibi) böyle önerdiği örneği gördük:Fortran'daki bir yapı yapıcısının nasıl geçersiz kılınacağı

module mymod 

    type mytype 
    integer :: x 
    ! Other stuff 
    end type 

    interface mytype 
    module procedure init_mytype 
    end interface 

contains 
    type(mytype) function init_mytype(i) 
    integer, intent(in) :: i 
    if(i > 0) then 
     init_mytype%x = 1 
    else 
     init_mytype%x = 2 
    end if 
    end function 
end 

program test 
    use mymod 
    type(mytype) :: x 
    x = mytype(0) 
end program 

Bu temelde (değişken isimleri yedekli nedeniyle hataların bir yığın oluşturur örneğin Hata: USULÜ özniteliği ile 'MyType yani' çatışmaların KAYNAKLANAN nitelik 1'de)). Fortran 2003 örneğinin sözlü bir kopyası benzer hatalar üretir. Bunu gfortran 4.4, ifort 10.1 ve 11.1'de denedim ve hepsi aynı hataları üretiyorlar.

Soruma soru: bu sadece Fortran 2003'ün bir imkansız özelliği mi? Yoksa bunu yanlış mı uyguluyorum?

Düzenleme: Bu sorunla ilgili olarak bir bug report ve bir announced patch ile karşılaştım. Ancak, hiçbir şans ve benzeri hatalarla bir Kasım gcc46 yapısını kullanmayı denedim.

Düzenleme 2: Yukarıdaki kod Intel Fortran 12.1.0 kullanarak çalışır.

cevap

6

Fortran 2008 standardının kopyasına danıştım. Bu türetilmiş tür ile aynı ada sahip bir genel bir arayüz tanımlamanıza olanak tanır. Derleyicim (Intel Fortran 11.1) kodu derlemeyecek, bu yüzden şüpheli kaldım (2003 standardının bir kopyası olmadan), bunun henüz Fortran 2003 standardının henüz kullanılmayan bir özelliği olduğunu düşünüyorum.

Ayrıca, programınızda bir hata var. İşleviniz beyanı: Neyse

type(mytype) function init_mytype(i) 
+0

Teşekkürler, düzeltildi. Rahatsız edici hata için özür dilerim, bu acele bir örnek oldu. –

17

Is it currently possible to override the structure constructor in Fortran?

sayılı:

type(mytype) function init_mytype 
    integer, intent(in) :: i 

belki de yeniden yazılmalıdır fonksiyon şartnamede, bulunmaz varlığını ve bir argüman hedefi belirler Yaklaşımınızı kullanmak bile, kurucu geçersiz kılma ile ilgili değildir. Ana nedeni yapı kurucusu # OOP kurucusudur. Bazı benzerlikler var ama bu sadece başka bir fikir.

Başlangıcı olmayan işlevinizi başlatma ifadesinde kullanamazsınız. Yalnızca sabit, dizi veya yapı yapıcı, içsel işlevler kullanabilirsiniz ... Daha fazla bilgi için Fortran 2003 taslağında 7.1.7 Başlatma ifadesine bakın. Tamamen

type(mytype) :: x 
x = mytype(0) 

ve

type(mytype) :: x 
x = init_mytype(0) 

ve ne mymod MODÜLÜ içindeki ARAYÜZ bloğunu kullanarak tüm noktasıdır arasındaki gerçek fark nedir anlamıyorum dikkate gerçeğinden hareketle

.

Açıkçası, dürüstçe bir fark var, büyük olanı - ilk yol yanıltıcıdır. Bu işlev yapıcı değildir (çünkü Fortran'da hiçbir OOP kurucusu yoktur), bir başlatıcıdır.

  1. Bellek tahsisi: Ana akım cepten Yapıcıda


    sırayla iki şey yapıyor sorumludur.

  2. Üye başlatma.

Farklı dillerdeki bazı örnek sınıf örneklerine bir göz atalım.

Java yılında:

MyType mt = new MyType(1); 

çok önemli bir gerçeği gizlenmiştir - nesne aslında bir sınıf türünde bir varibale bir göstericidir gerçeğini.

MyType* mt = new MyType(1); 

Ama

her iki dilde bir iki kurucu görevleri bile sözdizimi düzeyinde yansıtılmasını görebilirsiniz: C++ eşdeğer kullanarak yığın
üzerinde tahsisi olacaktır. İki bölümden oluşur: anahtar kelime yeni (tahsis) ve yapıcı adı (başlatma). Objective-C sözdiziminde bu gerçeği daha da vurgulanmaktadır:

MyType* mt = [[MyType alloc] init:1]; 

Çoğu zaman, ancak, yapıcı çağırma diğer bazı formunu görebilirsiniz. Yığın C tahsisi durumunda ++ aslında biz sadece bunu düşünmüyoruz böylece yanıltıcı özel (çok kötü) sözdizimi inşaatı

MyType mt(1); 

kullanır.

Python

mt = MyType(1) 

hem nesne aslında bir işaretçi ve tahsis sürüyorsunuz ilk (sözdizimi düzeyinde) gizli olmasıdır gerçeği yılında. Ve bu yöntem denir ... __init__! O_O Yanıltıcı. С ++ yığın tahsisi bununla karşılaştırıldığında kaybolur. =)


Neyse, dilde yapıcısı fikri yönteminin bazı özel tür kullanarak tek deyimi yılında tahsisini bir başlatma yapabilme yeteneğine işaret eder. Ve bunun "gerçek OOP" olduğunu düşünüyorsanız, senin için kötü haberlerim var. Hatta Smalltalkdoesn't have constructors. Sadece sınıflar üzerinde new yöntemine sahip olmak için bir kuraldır (bunlar meta sınıflarının tekil nesneleridir). Aynı amaca ulaşmak için Factory Design Pattern diğer birçok dilde kullanılmaktadır.

Fortran'daki modüller kavramının Modula-2'den esinlendiği bir yer okudum. Ve bana göre OOP özellikleri Oberon-2'dan ilham alıyor. Oberon-2'de de kurucu yoktur. Ancak elbette, önceden bildirilmiş prosedürün (örneğin, Fortran'daki ALLOCATE gibi, fakat ALLOCATE ifadesidir) saf tahsisi vardır. Tahsis ettikten sonra (pratikte) bazı başlatıcıları arayabilirsin, ki bu sadece sıradan bir yöntem. Orada özel bir şey yok.

Nesneleri başlatmak için bazı fabrikaları kullanabilirsiniz. Tekil nesneler yerine gerçekten modülleri kullandığınız şey bu. Ya da (Java/C#/... programcıların) sıradan işlevler yerine, sıradan işlevler yerine tekil nesneler yöntemlerini kullandıklarını söylemek daha iyidir (hiçbir modül - sıradan işlevlere sahip olmanın yolu yoktur, yalnızca yöntemler).

Ayrıca bunun yerine türüne bağlı SUBROUTINE kullanabilirsiniz. init altprogramın this arg için

MODULE mymod 

    TYPE mytype 
    PRIVATE 
    INTEGER :: x 
    CONTAINS 
    PROCEDURE, PASS :: init 
    END TYPE 

CONTAINS 

    SUBROUTINE init(this, i) 
    CLASS(mytype), INTENT(OUT) :: this 
    INTEGER, INTENT(IN) :: i 

    IF(i > 0) THEN 
     this%x = 1 
    ELSE 
     this%x = 2 
    END IF 
    END SUBROUTINE init 

END 

PROGRAM test 

    USE mymod 

    TYPE(mytype) :: x 

    CALL x%init(1) 

END PROGRAM 

INTENT(OUT) iyi olacak gibi görünüyor. Çünkü bu yöntemin, tahsis edildikten sonra sadece bir kez ve sağda çağrılmasını bekliyoruz. Bu varsayımın yanlış olmayacağını kontrol etmek iyi bir fikir olabilir. LOGICAL :: inited için boole bayrağı 'a eklemek için, .false. olup olmadığını kontrol edin ve ilk başlatma sonrasında .true. olarak ayarlayın ve yeniden başlatma girişiminde başka bir şey yapın. Google Gruplarında bu konuyla ilgili bir şeyler hatırlıyorum. Bunu bulamıyorum.

+2

Açıklama için teşekkür ederiz. Ben, saf OOP anlamında bir kurucu olmadığını ve benzer alternatif yaklaşımların aynı şeyin çoğunu gerçekleştireceğini anlıyorum. Daha ziyade, bu, yazarların spesifik çalışma taslaklarından birinde “yapı kurucusu” olarak adlandırmayı seçtikleri, p445'ten (C.1.6) neredeyse aynı değildir. Fortran'ın ortak uygulamalarında bu türden geçersiz kılmaların mümkün olup olmadığını merak ettim. Ama tavsiyeni kalbe götüreceğim, tekrar teşekkür ederim. –

İlgili konular