سؤال

هل من الممكن حاليًا تجاوز مُنشئ الهيكل في فورتران؟ لقد رأيت أمثلة مقترحة مثل هذا (كما في مواصفات Fortran 2003):

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

هذا يولد بشكل أساسي كومة من الأخطاء بسبب أسماء متغيرة زائدة عن الحاجة (مثل الخطأ: سمة مشتقة من "mytype" تعارض مع سمة الإجراء على (1)). نسخة حرفية من مثال Fortran 2003 يولد أخطاء مماثلة. لقد جربت هذا في Gfortran 4.4 و IFORT 10.1 و 11.1 وكلهم ينتجون نفس الأخطاء.

سؤالي: هل هذه مجرد ميزة لا تنفذ في Fortran 2003؟ أم أنا أقوم بتنفيذ هذا بشكل غير صحيح؟

تحرير: لقد صادفت أ تقرير الشوائب و أعلن التصحيح إلى Gfortran فيما يتعلق بهذه القضية. ومع ذلك ، فقد حاولت استخدام بناء نوفمبر من GCC46 دون حظ وأخطاء مماثلة.

تحرير 2: يبدو أن الرمز أعلاه يعمل باستخدام Intel Fortran 12.1.0.

هل كانت مفيدة؟

المحلول

لقد استشرت نسختي من معيار Fortran 2008. هذا يسمح لك بتحديد واجهة عامة مع نفس الاسم كنوع مشتق. لن يقوم المترجم الخاص بي (Intel Fortran 11.1) بتجميع الكود على الرغم من أنني تركت مشتبه به (بدون نسخة من معيار 2003 إلى يد) أن هذه ميزة غير محددة من معيار Fortran 2003.

إلى جانب ذلك ، هناك خطأ في برنامجك. إعلان وظيفتك:

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

يحدد وجود وقصد حجة غير موجودة في مواصفات الوظيفة ، والتي ربما ينبغي إعادة كتابةها على النحو التالي:

  type(mytype) function init_mytype(i)

نصائح أخرى

هل من الممكن حاليًا تجاوز مُنشئ الهيكل في فورتران؟

رقم. على أي حال ، حتى أن استخدام نهجك ليس تمامًا عن المباني المتجددة. السبب الرئيسي هو أن مُنشئ الهيكل # OOP. هناك بعض التشابه ولكن هذه مجرد فكرة أخرى.

لا يمكنك استخدام وظيفتك غير الداخلية في تعبير التهيئة. يمكنك فقط استخدام مُنشئ الثابت أو المصفوفة أو الهيكل ، وظائف جوهرية ، ... لمزيد من المعلومات ، ألقِ نظرة على تعبير التهيئة 7.1.7 في مسودة Fortran 2003.

مع الأخذ في الاعتبار ، لا أفهم تمامًا ما هو الفرق الحقيقي بين

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

و

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

وما هو الهدف من استخدام كتلة الواجهة داخل وحدة MyMod.

حسنًا ، بصراحة ، هناك اختلاف ، الفرق الضخمة - الطريقة الأولى مضللة. هذه الوظيفة ليست هي المنشئ (لأنه لا يوجد منشئات OOP على الإطلاق في فورتران) ، فهي عبارة عن مُهيئ.


في مُنشئ OOP السائد المسؤول عن القيام بأمرين متتابعين:

  1. تخصيص الذاكرة.
  2. تهيئة العضو.

دعونا نلقي نظرة على بعض الأمثلة على فصول التثبيت بلغات مختلفة.

في جافا:

MyType mt = new MyType(1);

حقيقة مهمة للغاية هي مخفية - حقيقة أن الكائن هو في الواقع مؤشر إلى متغير من نوع الفئة. المكافئ في C ++ سوف يكون تخصيص على كومة استخدام:

MyType* mt = new MyType(1);

ولكن في كلتا اللغتين يمكن للمرء أن يرى أن واجبات مُنشئين تنعكس حتى على مستوى بناء الجملة. يتكون من جزأين: الكلمة الرئيسية الجديدة (التخصيص) واسم مُنشئ (التهيئة). في ج موضوعية بناء الجملة هذه الحقيقة أكثر التأكيد:

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

في كثير من الأحيان ، يمكنك رؤية شكل آخر من أشكال الاحتجاج. في حالة ما اذا التخصيص على المكدس C ++ يستخدم بناء بناء الجملة الخاص (فقير جدًا)

MyType mt(1);

وهو في الواقع مضللة لدرجة أننا لا نستطيع التفكير فيه.

في بيثون

mt = MyType(1)

كل من حقيقة أن الكائن هو في الواقع مؤشر وحقيقة أن التخصيص يتم أولاً مخفي (على مستوى بناء الجملة). وهذه الطريقة تسمى ... __init__! O_O مضللة جدا. تخصيص с ++ تخصيص المكدس بالمقارنة مع ذلك. =)


على أي حال ، فكرة وجود البناء في اللغة تعني القدرة على القيام تخصيص تهيئة في بيان واحد باستخدام نوع خاص من الطرق. وإذا كنت تعتقد أن هذه طريقة "حقيقية" لدي أخبار سيئة لك. حتى حديث قصير ليس لديه منشئون. انها مجرد اتفاقية أن يكون new طريقة على الفصول نفسها (هم كائنات مفردة من فصول التعريف). ال نمط تصميم المصنع يستخدم في العديد من اللغات الأخرى لتحقيق نفس الهدف.

قرأت في مكان ما أن مفاهيم الوحدات النمطية في فورتران كانت مستوحاة من Modula-2. ويبدو لي أن ميزات OOP مستوحاة من أوبرون -2. لا يوجد منشئون في أوبرون -2 أيضًا. ولكن هناك بالطبع تخصيص خالص مع إجراء مسبق جديد (مثل التخصيص في Fortran ، ولكن التخصيص هو بيان). بعد التخصيص ، يمكنك (يجب في الممارسة العملية) استدعاء بعض التهيئة ، وهي مجرد طريقة عادية. لا شيء مميز هناك.

حتى تتمكن من استخدام نوع من المصانع لتهيئة الكائنات. هذا ما فعلته بالفعل باستخدام الوحدات النمطية بدلاً من كائنات Singleton. أو من الأفضل أن نقول إنهم (Java/C#/... ... المبرمجين) يستخدمون أساليب كائنات Singleton بدلاً من الوظائف العادية نظرًا لعدم وجودها اللاحق (لا توجد وحدات - لا توجد طريقة لوظائف عادية ، طرق فقط).

كما يمكنك استخدام روتين فرعي مرتبط بدلاً من ذلك.

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) إلى عن على this arg من init يبدو أن الروتين الفرعي بخير. لأننا نتوقع أن يتم استدعاء هذه الطريقة مرة واحدة فقط وبعد التخصيص. قد تكون فكرة جيدة للسيطرة على أن هذا الافتراض لن يكون خطأ. لإضافة بعض العلم المنطقي LOGICAL :: inited إلى mytype, ، تحقق مما إذا كان .false. وتعيينها على .true. عند التهيئة الأولى ، وافعل شيئًا آخر في محاولة لإعادة التهيئة. بالتأكيد أتذكر بعض الموضوعات حولها في مجموعات Google ... لا يمكنني العثور عليها.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top