ΠΑΝΕΠΙΣΤΗΜΙΟ ΘΕΣΣΑΛΙΑΣ ΤΜΗΜΑ ΜΗΧΑΝΟΛΟΓΩΝ ΜΗΧΑΝΙΚΩΝ ΒΙΟΜΗΧΑΝΙΑΣ Διάλεξη 5: Επαναληπτικές και εξωτερικές συναρτήσεις και διαδικασίες Εαρινό εξάμηνο 2009 ΠΡΟΓΡΑΜΜΑΤΙΣΜΟΣ Η/Υ Ι. Σαρρής, τηλ.
Εξωτερικές διαδικασίες Ιστορικά οι εξωτερικές διαδικασίες ήταν το μόνο διαθέσιμο είδος διαδικασιών στην Fortran 77 Η χρήση τους στην Fortran 90 περιορίζεται στην αυτόματη επίλυση ολοκληρωμένων υπο-προβλημάτων. Όπως και οι εσωτερικές διαδικασίες είναι και αυτές τύπου SUBROUTINE ή FUNCTION Δεν περιέχονται μέσα στην έκταση CONTAINS…END, αλλά είτε σε ένα άλλο αρχείο πηγαίου κώδικα (με την κατάληξη.F90) ή μετά από την πρόταση END PROGRAM Κάθε εξωτερική διαδικασία μεταγλωττίζεται ξεχωριστά, μπορεί να περιέχει εσωτερικές διαδικασίες και μπορούν να έχουν πολλαπλές εισόδους.
Εξωτερικές διαδικασίες (συνέχεια) Η κυριότερη διαφορά με τα άλλα είδη διαδικασιών είναι ότι οι εξωτερικές διαδικασίες δεν έχουν ρητή διεπιφάνεια. Πρακτικά αυτό σημαίνει ότι: 1.Ο μεταγλωττιστής δεν ξέρει κατά την μεταγλώττιση τον τρόπο κλίσης της διαδικασίας. 2.Ο προγραμματιστής πρέπει να έχει φροντίσει ώστε να καλεί την εξωτερική διαδικασία με τον σωστό τρόπο 3.Υπάρχει η δυνατότητα να δηλώσουμε ρητά την διεπιφάνεια των εξωτερικών διαδικασιών χρησιμοποιώντας την δομή INTERFACE… END INTERFACE, πχ INTERFACE [γενικός ορισμός] [διεπιφάνειες] [MODULE PROCEDURE λίστα διαδικασιών] END INTERFACE Όπου, [διεπιφάνειες] : Η αρχική και η τελική πρόταση μιας ή περισσότερων διαδικασιών μαζί με το τμήμα δηλώσεων της διαδικασίας.
Παραδείγματα INTERFACE REAL FUNCTION f(x,y) REAL, INTENT(IN)::x,y END FUNCTION f SUBROUTINE fa(x,y,z) REAL, INTENT(IN)::x,y REAL, INTENT(OUT)::z END SUBROUTINE fa END INTERFACE PROGRAM Prog_interface IMPLICIT NONE INTERFACE INTEGER ELEMENTAL FUNCTION f(x) INTEGER, INTENT(IN)::x END FUNCTION f END INTERFACE INTEGER::I INTEGER, DIMENTION(5)::a=(/(i,i=1,5)/) PRINT*, f(a) END PROGRAM Prog_interface INTEGER ELEMENTAL FUNCTION f(x) INTEGER, INTENT(IN )::x f=x**2-1 END FUNCTION f
Παρατηρήσεις Αν στο προηγούμενο παράδειγμα ξεχάσουμε την δομή INTERFACE, τότε θα δούμε ότι ο μεταγλωττιστής δεν θα μπορεί να επισημάνει το όνομα της διαδικασίας και θα βγάλει το μήνυμα λάθους: Error: unresolved external Εναλλακτικά μπορούμε να κάνουμε γνωστή την ύπαρξη της διαδικασίας χρησιμοποιώντας την εντολή EXTERNAL, π.χ: INTEGER, EXTERNAL :: f Γενικά, προτείνουμε την χρήση της δομής INTERFACE αφού γνωστοποιεί στο πρόγραμμα που την καλεί την ύπαρξη της εξωτερικής διαδικασίας και ταυτόχρονα διασφαλίζει την αντιστοίχηση των όρων των δύο ορισμάτων
Παρατηρήσεις (συνέχεια) Η χρήση ρητών διεπιφανειών είναι υποχρεωτική μόνο στις εξής περιπτώσεις: 1. Όταν χρησιμοποιούμε εικονικούς όρους που έχουν δηλωθεί ως OPTIONAL. 2.Όταν το αποτέλεσμα μιας FUNCTION είναι πίνακας 3.Όταν το αποτέλεσμα μιας FUNCTION είναι δείκτης 4.Όταν το αποτέλεσμα μιας FUNCTION είναι αλφαριθμητικό με άγνωστο μήκος 5.Όταν χρησιμοποιούμε πίνακα υποθετικής μορφής 6.Όταν η διαδικασία έχει εικονικούς όρους με τις ιδιότητες POINTER ή TARGET. 7.Όταν χρησιμοποιούμε λέξεις κλειδιά στο όρισμα κλήσης μιας διαδικασίας. 8.Όταν η διαδικασία είναι γενική (όταν χρησιμοποιούμε το ίδιο όνομα για την κλήση διαφορετικών διαδικασιών ανάλογα με το είδος των όρων του ορίσματος) 9.Όταν οι διαδικασίες είναι PURE, κλπ
Εικονικές διαδικασίες Μια άλλη διαφορά των εξωτερικών διαδικασιών είναι ότι τα ορίσματά τους μπορούν να χρησιμοποιηθούν ως όροι του ορίσματος μιας άλλης διαδικασίας. Άρα, η διαδικασία – όρος περνάει στην διαδικασία που καλείται. Αυτό είναι πολύ βολικό για παράδειγμα στην περίπτωση που θέλουμε να κάνουμε έναν υπολογισμό σε μια συνάρτηση που δεν είναι εκ των προτέρων γνωστή, πχ: PROGRAM derivative IMPLICIT NONE INTERFACE REAL FUNCTION df(f,z,dz) INTERFACE REAL FUNCTION f(x) REAL, INTENT(IN)::x END FUNCTION f END INTERFACE REAL, INTENT(IN)::z,dz END FUNCTION df END INTERFACE REAL::b=5; REAL, EXTERNAL::f PRINT*, f(a), df(f,a,0.1) END PROGRAM derivative REAL FUNCTION df(f,z,dz) INTERFACE REAL FUNCTION f(x) REAL, INTENT(IN)::x END FUNCTION f END INTERFACE REAL, INTENT(IN)::z,dz df=f(z+dz)-f(z-dz)/(2.*dz) END FUNCTION df REAL FUNCTION f(x) REAL, INTENT(IN)::x f=x*2-1 END FUNCTION f
Σχόλια Και οι δύο εξωτερικές διαδικασίες γνωστοποιούνται στο κυρίως πρόγραμμα αφού χρειάζεται να τις χρησιμοποιήσει. Μόνο η διαδικασία f γνωστοποιείται στο υποπρόγραμμα που υπολογίζει την παράγωγο. Αν χρησιμοποιούσαμε εσωτερικές διαδικασίες η χρήση των διεπιφανειών θα ήταν περιττή, Αλλά, έχουμε πετύχει την πλήρη αυτονομία του υποπρογράμματος που υπολογίζει την παράγωγο, και άρα μπορούμε να το χρησιμοποιήσουμε οπουδήποτε.
Συσχέτιση και εμβέλεια Εμβέλεια κάθε ονόματος ονομάζεται η έκταση στην οποία το όνομα είναι γνωστό. Έτσι έχουμε ονόματα γενικά και τοπικά. Η εικονική μεταβλητή είναι προφανώς τοπική μεταβλητή που ανταλλάσσει τιμή με κάποια που είναι τουλάχιστον τοπική της μονάδας που την καλεί. Πριν κληθεί η διαδικασία δεν σχετίζεται με κάποια θέση μνήμης Η συσχέτιση επιτρέπει σε διάφορες μονάδες προγράμματος να έχουν πρόσβαση στην ίδια θέση μνήμης. Στην Fortran 90 υπάρχουν τριών ειδών συσχετίσεις
Συσχέτιση (συνέχεια) Συσχέτιση ονόματος: γίνεται με τρεις τρόπους: μέσω ορίσματος: όπως μέσω του ορίσματος των διαδικασιών μέσω ξενιστή: ξενιστής λέγεται μια μονάδα κώδικα που φιλοξενεί διαδικασίες. Τα ονόματα που έχουνυπόσταση και εμβέλεια στην μονάδα ξενιστή έχουν επίσης υπόσταση και σε όλες τις εσωτερικές της διαδικασίες. με USE : με την εντολή USE μπορούμε να κάνουμε διαθέσιμα τα δεδομένα ενός αρθρώματος σε μια άλλη μονάδα κώδικα. Συσχέτιση μνήμης:χρησιμοποιώντας τις εντολές COMMON, EQUIVALENCE και NAMELIST. Συσχέτιση δείκτη
Παράδειγμα REAL:: A=1, B= 2, C = 3 CALL ADDONE PRINT*,A,B,C ! Τυπώνει CONTAINS SUBROUTINE ADDONE A=A+1; B=B+1; C=C+1 END SUBROUTINE END Όπως βλέπουμε, οι τιμές των μεταβλητών είναι γνωστές τόσο στο κυρίως πρόγραμμα όσο και στην εσωτερική διαδικασία. Πρόκειται για τις ίδιες μεταβλητές, χωρίς να χρησιμοποιούνται εικονικές μεταβλητές στην έκταση της διαδικασίας. Σε αυτή την περίπτωση, τα ονόματα της διαδικασίας συσχετίζονται μέσω ξενιστή με τα ονόματα του κυρίως προγράμματος.
Σχόλια (συνέχεια) Οι προηγούμενες μεταβλητές ονομάζονται γενικές επειδή είναι γνωστές από όλες τις μονάδες του προγράμματος. Γενικά οι εσωτερικές διαδικασίες γνωρίζουν την τιμή: Των τοπικών τους μεταβλητών Των εικονικών μεταβλητών Των μεταβλητών που έχουν δηλωθεί στο πρόγραμμα που τις φιλοξενεί στην έκταση PROGRAM…CONTAINS REAL:: A=1, B= 2, C = 3 CALL ADDONE PRINT*,A,B,C ! Τυπώνει PRINT*,X ! Τυπώνει 0.0 CONTAINS SUBROUTINE ADDONE REAL:: X=1 A=A+X; B=B+X; C=C+X END SUBROUTINE END
Σχόλια (συνέχεια) REAL:: A=1, B= 2, C = 3, X=1 CALL ADDONE(A,B,C,X) PRINT*,A,B,C ! Τυπώνει PRINT*,X ! Τυπώνει 1.0 CONTAINS SUBROUTINE ADDONE(A,B,C,X) REAL:: A,B,C,X A=A+X; B=B+X; C=C+X END SUBROUTINE END Αντίθετα με τις εσωτερικές διαδικασίες, οι εξωτερικές δεν μπορούν να έχουν συσχέτιση μέσω ξενιστή με την μονάδα που τις καλεί.
RECURSIVE INTEGER FUNCTION Factorial(I) RESULT(Answer) IMPLICIT NONE INTEGER, INTENT(IN):: I IF (I==0) THEN Answer=1 ELSE Answer=I*Factorial(I-1) END IF END FUNCTION Factorial Αναδρομικές συναρτήσεις PROGRAM test_rec IMPLICIT NONE INTEGER :: I, F, Factorial PRINT *,' Type in the number, integer only' READ *,I DO WHILE(I<0) PRINT *,' Factorial only defined for ' PRINT *,' positive integers: Re-input' READ *,I END DO F=Factorial(I) PRINT *,' Answer is', F END PROGRAM test_rec Παράδειγμα, παραγοντικό: 5!=5*4! 4!=4*3! 3!=3*2! 2!=2*1! 1!=1 και άρα 5! = 5*4*3*2*1 ή 120.
Αρθρώματα Ένα άρθρωμα δημιουργείται σε ένα ξεχωριστό αρχείο που περιέχει πηγαίο κώδικα με την παρακάτω σύνταξη: MODULE όνομα [δηλώσεις] [ CONTAINS ] [διαδικασίες αρθρώματος] END [ MODULE [όνομα]] Όπου, στις δηλώσεις μπορεί να περιλαμβάνει δηλώσεις τύπου δεδομένων ή διαδικασιών, και τις εντολές: ALLOCATABLE, COMMON, EQUIVALENCE, DATA, DIMENSION, EXTERNAL, IMPLICIT, INTENT, INTERFACE…END INTERFACE, INTRINSIT, NAMELIST, OPTIONAL, PARAMETER, POINTER, PRIVATE, PUBLIC, SAVE,TARGET, USE. Δεν μπορεί να περιλαμβάνει εντολές FORMAT και ENTRY.
Αρθρώματα (συνέχεια) Το άρθρωμα δεν είναι εκτελέσιμο από μόνο του, αλλά μπορεί να έχει κομμάτια εκτελέσιμου κώδικα στην έκταση CONTAINS…END MODULE ως διαδικασίες του αρθρώματος. Οι διαδικασίες αρθρώματος μπορεί να είναι και πάλι τύπου SUBROUTINE ή FUNCTION και μπορεί να περιλαμβάνουν την εντολή ENTRY. Για να μπορέσουμε να χρησιμοποιήσουμε ένα άρθρωμα πρέπει να το δηλώσουμε με την εντολή USE: USE όνομα αρθρώματος [, ONLY: λίστα ονομάτων] Όπου, με τη λίστα ονομάτων περιορίζουμε την πρόσβαση μόνο στα δεδομένα και τις διαδικασίες που αναφέρονται στην λίστα.
Παράδειγμα PROGRAM modulexample USE procmod REAL:: Y=1 CALL pass(Y); PRINT*,Y CALL pass2; PRINT*,Y B=B+1;PRINT*,Y CONTAINS SUBROUTINE pass2 Y=Y-B END SUBROUTINE pass2 END PROGRAM modulexample MODULE procmod REAL:: B=2.0 CONTAINS SUBROUTINE pass(X) REAL:: X X=X+B END SUBROUTINE pass END MODULE procmod !Τυπώνει: ! !
Παράδειγμα PROGRAM modulexample USE procmod, ONLY:PASS REAL:: Y=1 CALL pass(Y); PRINT*,Y CALL pass2; PRINT*,Y B=B+1;PRINT*,Y CONTAINS SUBROUTINE pass2 Y=Y-B END SUBROUTINE pass2 END PROGRAM modulexample !Τυπώνει: ! ! Όταν χρησιμοποιείται το χαρακτηριστικό ONLY μιλάμε για περιορισμό πρόσβασης στο χρήστη. Το πρόγραμμα στο παραπάνω παράδειγμα δεν ξέρει την τιμή του Β!
Αρθρώματα (συνέχεια) Οι γενικές μεταβλητές είναι καλό να χρησιμοποιούνται για δεδομένα που θέλουμε να μοιραστούμε με όλες τις μονάδες κώδικα. Σε κάθε άλλη περίπτωση είναι ευκολότερη η συσχέτιση με ορίσματα και εικονικές μεταβλητές. Ο περιορισμός πρόσβασης μπορεί να γίνει επίσης και στην πηγή, δηλαδή στο άρθρωμα, χρησιμοποιώντας τις εντολές / ιδιότητες PRIVATE και PUBLIC. Η σύνταξή τους είναι: PUBLIC [[::] λίστα] ή δήλωση τύπου, PUBLIC :: λίστα και PRIVATE [[::] λίστα] ή δήλωση τύπου, PRIVATE :: λίστα Η λίστα περιλαμβάνει ονόματα δεδομένων και διαδικασιών Όλα τα ονόματα και οι διαδικασίες είναι καταρχήν PUBLIC (άρα προσβάσιμα από οποιαδήποτε ομάδα χρησιμοποιεί το άρθρωμα) Αν δηλωθούν PRIVATE είναι εσωτερικά του αρθρώματος και δεν επιτρέπεται η πρόσβαση από εξωτερικές μονάδες Χωρίς λίστα είναι είτε PUBLIC είτε PRIVATE
Διαφορές μεταξύ των διαδικασιών Είδη διαδικασιών ΕσωτερικήΕξωτερικήΑρθρώματοςΕγγενής Μπορεί να είναι RECURSIVE ναι Μπορεί να περιέχει CONTAINS όχιναι Μπορεί να περιέχει ENTRY όχιναι Μπορεί να έχει όρους OPTIONAL ναι Μπορεί να είναι γενική όχιναι Μπορεί να είναι ELEMENTAL ναι Έχει ρητή διεπιφάνεια ναιόχιναι Όροι με λέξεις κλειδιά ναι Χρήση σε INTERFACE όχιναιόχι Χρήση για ορισμό τελεστών όχιναι όχι Χρήση σαν όρος όχιναι
Παράδειγμα PROGRAM example USE procmod IMPLICIT NONE REAL:: Y=1 CALL pass; PRINT*,Y CALL pass2(Y); PRINT*,Y CALL pass3; PRINT*,Y CONTAINS SUBROUTINE pass Y=Y-B END SUBROUTINE pass END PROGRAM example MODULE procmod IMPLICIT NONE REAL:: B=2.0 CONTAINS SUBROUTINE pass2(X) EXTERNAL pass3 REAL:: X CALL pass3(X) X=add(X) CONTAINS REAL FUNCTION add(W) REAL, INTENT(IN)::W add=W+B END SUBROUTINE add END SUBROUTINE pass2 END MODULE procmod SUBROUTINE pass3 USE procmod REAL:: Z Z=Z*f(Z) CONTAINS REAL FUNCTION f(U) REAL, INTENT(IN)::U f=U+B END FUNCTION f END SUBROUTINE pass3 !Τυπώνει: ! !
Πολλαπλές είσοδοι Οι διαδικασίες αρθρώματος μπορούν να έχουν πολλαπλές εισόδους. Αυτό γίνεται με τη χρήση της εντολής ENTRY που έχει την παρακάτω σύνταξη: ENTRY όνομα (όρισμα) Μια ή περισσότερες εντολές ENTRY μπορούν να τοποθετηθούν στην έκταση της διαδικασίας και να συνδεθούν με RETURN για να χωρίσουν μια διαδικασία σε πολλές. Στην ουσία με κάθε ENTRY δημιουργούμε μια καινούργια διαδικασία. (κάτι παρόμοιο θα μπορούσε να γίνει με την εντολή CASE αλλά η ENTRY επιτρέπει να καλούμε την διαδικασία με πολλαπλά ορίσματα)
Παράδειγμα PROGRAM entryexample USE util READ(*,*) A,B,C IF(A==0) THEN PRINT*,eval(B,C) ELSE PRINT*,evalb(A,B,C) END IF END PROGRAM entryexample MODULE util REAL:: A,B,C CONTAINS REAL FUNCTION eval(X,Y) REAL:: X,Y,Z eval=(X+Y)*(X+Y) RETURN ENTRY evalb(X,Y,Z) eval=(X+Y+Z)*(X+Y+Z) END FUNCTION eval END MODULE util PROGRAM entryexample2 USE util READ(*,*) A,B,C IF(A==0) THEN PRINT*,eval(B,C) ELSE PRINT*,eval(A,B,C) END IF END PROGRAM entryexample2 MODULE util2 REAL:: A,B,C CONTAINS REAL FUNCTION eval(X,Y,Z) REAL, INTENT(IN):: X,Y REAL, OPTIONAL, INTENT(IN):: Z IF(PRESENT(Z)) THEN eval=(X+Y+Z)*(X+Y+Z) ELSE eval=(X+Y)*(X+Y) END IF END FUNCTION eval END MODULE util2
Συσχέτιση μνήμης COMMON :δηλώνει μια σειρά από μεταβλητές. Είναι ένας τρόπος για να μεταφέρουμε τιμές ανάμεσα σε διαφορετικές μονάδες κώδικα EQUIVALENCE :δηλώνει ότι δύο ή περισσότερες μεταβλητές χρησιμοποιούν την ίδια διεύθυνση μνήμης. NAMELIST :χρησιμοποιείται κυρίως για είσοδο και έξοδο. COMMON [/[όνομα]/] λίστα[,][/όνομα2/λίστα2,...] EQUIVALENCE (λίστα) [, (λίστα2),...] πχ, COMMON /numbers/A,B,C,D,RESULT πχ, EQUIVALENCE (A,RESULT)
Συσχέτιση μνήμης (συνέχεια) Το COMMON πρέπει να επαναλαμβάνεται στο τμήμα δηλώσεων μάθε μονάδας προγράμματος με την οποία θέλουμε να συσχετίσουμε τιμές. Το όνομά του πρέπει να είναι ίδιο, αλλά τα ονόματα στη λίστα μπορεί να είναι διαφορετικά. Σε αυτή τη περίπτωση υπάρχει αντιστοιχία ένα προς ένα ανάμεσα στα ονόματα. Ένα όνομα μεταβλητής δεν μπορεί να εμφανίζεται σε περισσότερα από ένα COMMON στην ίδια μονάδα κώδικα. Δεν μπορεί να περιέχει ονόματα εικονικών μεταβλητών, δυναμικών πινάκων, ονόματα FUNCTION και ονόματα ENTRY. Δεν μπορεί να περιέχει σταθερές που έχουν δηλωθεί με PARAMETER ή μεταβλητές που παίρνουν αρχική τιμή με DATA. Οι ίδιοι περιορισμοί ισχύουν για το EQUIVALENCE.
Παράδειγμα REAL:: A=1, B=2, C=3, D = 4, RESULT COMMON /numbers/ A, B, C, D, RESULT CALL addnumbers; PRINT*, RESULT END SUBROUTINE addnumbers REAL:: X, Y, W, W, ISON REAL:: ISON, KAI COMMON /numbers/ X, Y, Z, W, ISON EQUIVALENCE(ISON,KAI) KAI=X+Y+Z+W END SUBROUTINE ! Τυπώνει: 10.0 SUBROUTINE addnumbers REAL:: X, Y, W, W, ISON ! REAL:: ISON, KAI COMMON /numbers/ X, Y, Z, W, ISON EQUIVALENCE(ISON,KAI) KAI=X+Y+Z+W END SUBROUTINE ! Τυπώνει: E-44
Αντικειμενοστρεφής προγραμματισμός (ΑΠ) Η ποιο μοντέρνα τάση στον προγραμματισμό. Πλησιάζει πολύ στην προσομοίωση φυσικών εννοιών Βοηθάει σημαντικά στην αύξηση της παραγωγικότητας: 1.Μέσω της αύξησης της επαναχρησιμοποίησης κομματιών κώδικα 2.Λόγω των δυνατοτήτων σταδιακής ή ομαδικής ανάπτυξης κώδικα 3.Λόγω των καθαρών εκφράσεων που βοηθούν στη στην κατανόηση και την ευκολότερη επίλυση των προβλημάτων
ΑΠ (συνέχεια) Οι σύγχρονες γλώσσες ΑΠ διαθέτουν την δυνατότητα υλοποίησης τριών χαρακτηριστικών: Ενθυλάκωση: η δυνατότητα δημιουργίας κλάσεων, δηλαδή μονάδων με αυτόνομη χρησιμότητα. Κληρονομικότητα: η δυνατότητα δημιουργίας ιεραρχικών δομών δεδομένων. Πολυμορφισμός: η δυνατότητα δημιουργίας ενιαίων διεπιφανειών για διαφοροποιημένη χρήση ανάλογα με το είδος των δεδομένων.
ΑΠ (συνέχεια) Το αντικείμενο συνδυάζει τους βασικούς τύπους δεδομένων σε ένα σύνολο ορίζοντας ένα νέο είδος μεταβλητής. Υλοποιείται με την κατασκευή TYPE…END TYPE TYPE rectangle REAL:: Α,Β END TYPE TYPE(rectangle):: Z Z%A=2.; Z%B=3. Υπάρχει δυνατότητα δημιουργίας ειδικών τελεστών που εκτελούν πράξεις μεταξύ αντικειμένων του ίδιου ή διαφορετικού τύπου, και η δυνατότητα υπερφόρτωσης των βασικών τελεστών ώστε να μπορούν να εκτελούν πράξεις και μεταξύ των αντικειμένων. Στην Fortran υλοποιείται με τις κατασκευές: INTERFACE OPERATOR() … END INTERFACE για τους νέους ή τους βασικούς τελεστές, και INTERFACE ASSIGNMENT(=) … END INTERFACE για τον τελεστή ορισμού ‘=’.
ΑΠ (συνέχεια) Η κλάση ενσωματώνει τα αντικείμενα μαζί με προτάσεις που καθορίζουν την κατάστασή τους, τους αναγκαίους τελεστές, και διαδικασίες που υλοποιούν τους τελεστές, έχουν πρόσβαση στα αντικείμενα και δυνατότητες μεταβολής τους. Η κλάση υλοποιείται πλήρως στη fortran με τη χρήση της δομής MODULE…END MODULE Η κλάση μπορεί να έχει την δυνατότητα απόκρυψης δεδομένων από τις άλλες μονάδες προγράμματος (με χρήση των εντολών PRIVATE και PUBLIC )
Παράδειγμα PROGRAM Rectangle1 USE Class_Shape IMPLICIT NONE TYPE (rectangle):: tetragono REAL :: area = 0.0 tetragono= Make_Shape(4.,2.) area= Shape_Area(tetragono) WRITE(*,10) tetragono, area 10 FORMAT ('Area of',F5.2, ' by', F5.2,' & Rectangle is:', F6.2) END PROGRAM Rectangle1 ! Τυπώνει: Area of 4.00 by 2.00 Rectangle is: 8.00 MODULE Class_Shape IMPLICIT NONE TYPE rectangle REAL:: base, height END TYPE rectangle CONTAINS TYPE (rectangle) FUNCTION Make_Shape(x,y) RESULT(z) REAL, INTENT(IN):: x,y z = rectangle (x,y) END FUNCTION Make_Shape FUNCTION Shape_Area(x) RESULT(area) TYPE (rectangle), INTENT(IN):: x REAL:: area area=x%base*x%height END FUNCTION Shape_Area END MODULE Class_Shape PRINT*, X*Y END
Παραδείγματα Πολυμορφισμός: 10-18, σελ. 367 Υπερφόρτωση τελεστών: 10-19, σελ. 371 Κληρονομικότητα: 10-20, σελ. 373
Λίστες Οι δείκτες μας δίνουν τη δυνατότητα δημιουργίας δυναμικών δομών όπως οι συνδεδεμένες λίστες (ουρές, σωρούς, δενδριτικές δομές, κλπ) Οι δομές αυτές μας δίνουν την δυνατότητα της κατά βούλησης αύξησης και μείωσης του μεγέθους τους κατά την διάρκεια της εκτέλεσης. TYPE list INTEGER ::value TYPE (list), POINTER::next ! Αναδρομική δήλωση END TYPE list
Λίστες (συνέχεια) Η περιγραφή του τύπου list είναι αναδρομική Δεν έχουμε δηλώσει πουθενά το μέγεθος της λίστας Η δημιουργία της λίστας μπορεί να χωριστεί σε τέσσερα στάδια 1.Δημιουργείται ο τύπος της λίστας με την αναδρομική δήλωση TYPE list … END TYPE list, και δηλώνονται δύο δείκτες αυτού του τύπου. Αρχικά αποσυσχετίζονται από κάθε πιθανό στόχο. first NULL last NULL
Λίστες (συνέχεια) 2. Για να δημιουργήσουμε το πρώτο στοιχείο της λίστας συσχετίζουμε τους δύο δείκτες μεταξύ τους (last=>first), αποσυσχετίζουμε το επόμενο στοιχείο της λίστας (last%next=>null()) και δίνουμε τιμή (last%value=number) value nextNULL firstlast
Λίστες (συνέχεια) 3. Δημιουργείται κάθε στοιχείο της λίστας (last =>last%next) το επόμενο στοιχείο αποσυσχετίζεται (last%next =>null()) και το τρέχον παίρνει τιμή (last%value=number) value next value nextNULL first last
Λίστες (συνέχεια) value next value next value nextNULL first last 4. Με την εντολή first =>first%next διατρέχουμε την λίστα από την αρχή προς το τέλος της
Παράδειγμα PROGRAM linkedlist IMPLICIT NONE TYPE list INTEGER ::value TYPE (list), POINTER::next END TYPE list TYPE(list), POINTER ::first,last INTEGER:: number, status NULLIFY(first,last) READ*, number IF(number/=0) THEN ALLOCATE(first, STAT=status) IF(status/=0) STOP ‘NOT ENOUGH MEMORY’ last=>first last%next=>NULL() last%value= number reading:DO READ(*,*) number; IF(number==0) EXIT ALLOCATE(last%next, STAT=status) IF(status/=0) STOP ‘NOT ENOUGH MEMORY’ last=>last%next last%next=>NULL() last%value= number END DO reading END IF printing:DO WHILE(ASSOCIATED(first)) PRINT*, first%value first=>first%next END DO printing END PROGRAM linkedlist