2. Ομάδες (Αντικείμενα)
(Αλλαγές από 1/4/2017)
2.1. Η μεταβλητή ως μήνυμα!
Είδαμε ότι με ονόματα τμημάτων/συναρτήσεων μπορούμε να φτιάξουμε κώδικα για συγκεκριμένες εργασίες. Αυτές οι εργασίες γίνονται πάνω σε δεδομένα που γράφουμε με το χέρι, ή που εισάγουμε. Είδαμε την έννοια του προσωρινού, όπου η μεταβλητή που εισάγουμε ένα νούμερο μπορεί να το δώσει σε ένα σωρό τιμών και με τη κλήση του τμήματος να διαβαστεί από το σωρό σε μια άλλη μεταβλητή και να την επεξεργαστούμε. Ας δούμε ένα απλό παράδειγμα, π.χ. στο τμήμα Α
(Σ Α enter)
Εισαγωγή "Αριθμός=",Α
Τμήμα ΚάνεΚάτι {
Διάβασε Κ
Τύπωσε Κ*2
}
ΚάνεΚάτι Α
(πλήκτρο Esc και βγαίνουμε στη γραμμή εργασιών)
Εδώ στο παράδειγμα το τμήμα το ορίζουμε πριν το χρησιμοποιήσουμε. Θα μπορούσαμε να το είχαμε γενικό δηλαδή με Σ Α φτιάχνω αυτό:
Εισαγωγή "Αριθμός=",Α
ΚάνεΚάτι Α
Και με Σ ΚάνεΚάτι
Διάβασε Κ
Τύπωσε Κ*2
(με Esc βγαίνουμε από το διορθωτή)
Το παρακάτω στην έκδοση 9 δεν έχει την ίδια απόκριση, διότι αν πατήσουμε άμεσα το enter δίνει τιμή 0, και επιπλέον δεν δέχεται χαρακτήρες που δεν δίνουν αριθμό. Όμως το πρόγραμμα εκτελείται. Δεν βγαίνει ποτέ το οκ ψευδές.
Αν δώσουμε άμεσα ένα enter τότε βγαίνει λάθος. Για να αποτρέψουμε το λάθος (είναι πιο σύνθετο γιατί πρέπει να αποφασίσουμε τι θα γίνει αν κάποιος δεν δώσει νούμερο. εδώ βλέπουμε δυο δομές, την Επανέλαβε { } Μέχρι, για επανάληψη μέχρι μια συνθήκη να δώσει αληθές και την Δες {} η οποία σταματάει τα λάθη από το να διακόπτουν το πρόγραμμα):
Επανέλαβε {
Δες οκ {
Εισαγωγή "Αριθμός=",Α
}
Αν όχι οκ τότε Τύπωσε
} Μέχρι οκ
Το τμήμα ΚάνεΚάτι πήρε ένα μήνυμα, έναν αριθμό και δουλειά του ήταν να το επεξεργαστεί και εδώ μας τύπωσε τον αριθμό επί 2. Δίνω 20 παίρνω 40.
Παρατηρούμε πως εισάγουμε μια μεταβλητή Α με τιμή και πως την περνάμε στο τμήμα σε μια Κ. Αυτό συμβαίνει γιατί το τμήμα ΚάνεΚάτι δεν μπορεί να διαβάσει την Α εκτός και αν την ορίσουμε ως γενική μεταβλητή (εδώ χωρίς το Επανέλαβε/Δες για το χειρισμό του λάθους)
Γενική Α
Εισαγωγή "Αριθμός=",Α
Τμήμα ΚάνεΚάτι {
Τύπωσε Α*2
}
ΚάνεΚάτι
2.2. Τι είναι Κατάσταση (State);
Παρατηρούμε βέβαια ότι το μήνυμα ήταν για άμεση κατανάλωση! Και βέβαια με χρήση γενικής το τμήμα μας δουλεύει μόνο για την συγκεκριμένη μεταβλητή. Τι γίνεται αν θέλουμε να δώσουμε δυο φορές ένα νούμερο και κάθε φορά το αποτέλεσμα του μηνύματος Α να επιδρά και στο νέο Α.
Δηλαδή ξεκινάω με Α_κατάσταση=10 και δίνω μήνυμα Α=20 και παίρνω 50 και μετά με Α=30 παίρνω 110 (30*2+50) και μετά με Α=40 παίρνω 190 (40*2+110)
Δηλαδή θέλω να μένει η κατάσταση μέσα στο τμήμα με κάποιο τρόπο:
Ξεκινώ με τον πιο απλό που μπορώ να σκεφτώ (δεν πειράζει αυτό, μάλιστα επιβάλλεται όταν δεν έχουμε κατασταλάξει πώς θα πετύχουμε κάτι, στο απλό βρίσκουμε το λάθος πιο γρήγορα)
Γενική Α, Β=10
Τμήμα ΚάνεΚάτι {
Τύπωσε Α*2+Β
Β<=Α*2+Β
}
Επανέλαβε {
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
ΚάνεΚάτι
} Πάντα
Δείτε πως στην Β καταχωρώ με <=. Αν δεν το έκανα αυτό τότε θα καταχωρούσα σε τοπική μεταβλητή Β (ο διερμηνευτής δίνει προτεραιότητα στην δημιουργία τοπικών) και κάθε φορά στα δεξιά θα έχω την Β (γενική με τιμή 10) και το αποτέλεσμα θα πήγαινε στη τοπική Β που θα διαγραφόταν στο τέλος!
Κάθε φορά που καλούμε την ΚάνεΚάτι το αποτέλεσμά της εξαρτάται από την Α που μόλις δώσαμε και την Β που είχε ήδη μια τιμή και ίσως άγνωστη σε μας (π.χ. άλλος έδωσε τα πρώτα νούμερα στο πρόγραμμα, το άλλος δείτε το ως γεγονός, ως κάτι που έφερε την τρέχουσα κατάσταση).
Δηλαδή το μήνυμα που δίνουμε αλλάζει την κατάσταση του τμήματος! Αλλά εδώ για να το πετύχουμε έχουμε γενικές μεταβλητές. Μπορεί να γίνει και με άλλους τρόπους, όπως θα δούμε. Η ιδέα όμως να κρατάμε τη κατάσταση σε ένα τμήμα του προγράμματός μας είναι βασική. Πχ σε ένα παιχνίδι κάπου κρατάμε το σκορ, ακόμα και αν αλλάζουμε επίπεδα, ή πίστες όπως λέμε. Αυτό σημαίνει ότι αποθηκεύουμε τη τρέχουσα κατάσταση του σκορ. Η έννοια της τρέχουσας κατάστασης μαζί με την έννοια της επόμενης κατάστασης, είναι βασικές γιατί όταν σχηματίσουμε για συγκεκριμένο ζήτημα το τι είναι αυτό που "γνωρίζει" το πρόγραμμα ως τρέχουσα κατάσταση και τι επιδιώκουμε να αλλάξει στην νέα κατάσταση τότε και μόνο τότε ξέρουμε τι γίνεται και είναι θέμα επιλογής της υλοποίησης για αυτό.
Οι αλλαγές καταστάσεων δεν γίνονται χωρίς ένα μήνυμα (σε μια μεταβλητή) να δώσει το έναυσμα για αυτό. Έτσι η ροή ενός προγράμματος χαρακτηρίζεται από την χρήση των μηνυμάτων, όπως έχει προγραμματιστεί, αλλά σίγουρα για να πούμε τι ακολουθεί, ποια είναι η νέα κατάσταση, δεν έχει μόνο σημασία το πρόγραμμα αλλά και το τι περιεχόμενο έχει το μήνυμα. Πολλές φορές έχουμε ακούσει ότι με λάθος στοιχεία παίρνουμε λάθος αποφάσεις, και ας ακολουθούμε σωστή μεθοδολογία. Ακριβώς αυτό παρατηρούμε και στο προγραμματισμό. Αν έχουμε δει τη συμπεριφορά ενός προγράμματος και την θεωρούμε σωστή για ένα σύνολο εισαγωγών, δεν σημαίνει ότι είναι ένα σωστό πρόγραμμα για κάθε άλλο σύνολο. και ενδεχομένως να συμβεί να μπει εισαγωγή που δεν είχε υπολογιστεί από τον προγραμματιστή και να έχουμε σφάλμα!
Η κατάσταση λοιπόν ενός τμήματος κώδικα, ας το αναφέρουμε με τον απλό αυτό τρόπο, σχετίζεται και με το πως γράφεται ο κώδικας αλλά και με το τι μεταφέρει, τι τιμές έχει σε μεταβλητές σε κάθε νέα εκτέλεση.
2.3. Στατικές Μεταβλητές
Μια άλλη προσέγγιση έχει να κάνει με την έννοια της στατικής μεταβλητής:
Η Μ2000 μπορεί να φτιάχνει στατικές μεταβλητές σε τμήματα και συναρτήσεις (και τελεστές, είδος συναρτήσεων για ομάδες). Στατικές μπορούν να είναι απλές μεταβλητές όπως Α ή Α$ ή Α%, όχι πίνακες δηλαδή, αν και υπάρχει αντικείμενο πίνακας που μπορεί να περαστεί με αναφορά σε μια απλή μεταβλητή αλλά δεν θα το δούμε αυτό εδώ.
Γενική Α
Τμήμα ΚάνεΚάτι {
Στατική Β=10
Τύπωσε Α*2+Β
Β=Α*2+Β
}
Επανέλαβε {
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
ΚάνεΚάτι
} Πάντα
Τώρα έχουμε μια ίδια απόκριση. Η Β θα γίνει 10 μια φορά, δηλαδή το =10 δίνει την αρχική τιμή. Την επόμενη που θα κληθεί η ΚάνεΚάτι θα δει ο διερμηνευτής ότι υπάρχει η Β και δεν θα της δώσει την αρχική τιμή. Η τιμή της Β φυλάσσεται χώρια, και παρόλο που το τμήμα θα τερματίσει και όλες οι τοπικές (λέγονται και αυτόματες) θα διαγραφούν, οι στατικές θα παραμείνουν στο αντικείμενο εκτέλεσης του τμήματος, και μόλις και αυτό τερματίσει όλες οι στατικές θα παραμείνουν στο σύστημα.
Στο παράδειγμα μπορούμε να κατανοήσουμε την αποθήκευση της στατικής με δυο τρόπους:
1. Τρέχουμε το τμήμα που έχουμε γράψει το παράδειγμα, έστω Α και δίνουμε διαδοχικά την ίδια τιμή έστω 12 στην εισαγωγή αριθμού.
2. Βγαίνουμε εκτός μετά και ξαναμπαίνουμε στο τμήμα που θα δημιουργήσει το τμήμα ΚάνεΚάτι, και τότε θα βρεθεί πάλι η στατική με τη τελευταία τιμή. Δηλαδή παρόλο που δεν θα υπάρχει το τμήμα ΚάνεΚάτι εντός του τμήματος (επειδή έχουμε βγει από αυτό και διαγράφτηκε), οι στατικές θα παραμείνουν αποθηκευμένες και θα αποδοθούν την επόμενη φορά που θα το δημιουργήσουμε και θα το καλέσουμε.
Για να σβήσουν οι στατικές απαιτείται η εντολή Καθαρό, ή αν θέλουμε να σβήσουμε όλα τα τμήματα η εντολή Νέο.
Για τα δυο τελευταία παραδείγματα φαίνεται να έχουν την ίδια λειτουργία, όσο στο δεύτερο με την στατική δεν διακόψουμε και εκκινήσουμε! Στη δεύτερη εκκίνηση αυτό που λείπει είναι η αρχικοποίηση της στατικής, η οποία δεν γίνεται γιατί ήδη υπάρχει! Η απουσία "αλλαγής" τιμής είναι και αυτή με την ίδια έννοια ταυτόσιμη με την παρουσία αλλαγής, άρα και αυτό αποτελεί μήνυμα ως έναυσμα για αλλαγή κατάστασης.
Δείτε ότι το πέρασμα νέας τιμής έγινε με απλό =. Δεν είναι απλά τοπική η στατική μεταβλητή, αλλά και εντελώς, είναι ιδιωτική! Δεν γίνεται να διαβαστεί από πουθενά αλλού. Ουσιαστικά δεν είναι "δεμένη" με το τμήμα αλλά με το αντικείμενο που τρέχει το τμήμα, δηλαδή με εκείνο που το καλεί!
Έτσι αν έχουμε ένα γενικό τμήμα και έχει στατική μεταβλητή τότε για κάθε κλήση του από διαφορετικό τμήμα θα έχει διαφορετικό σετ στατικών.
Εδώ αξίζει να σημειωθεί ότι σε άλλες γλώσσες οι στατικές έχουν τον ίδιο χώρο, άρα δίνουν την ίδια τιμή ανεξάρτητα από που κλήθηκε η συνάρτηση που τις περιέχει. Στη Μ2000 η κλήση συνάρτησης σχετίζεται με τη σειρά εκτέλεσης που καλούμε, άρα θέλουμε οι στατικές να έχουν να κάνουν με αυτό και όχι με κάποιο άλλο.
Ένα τμήμα που έχει στατικές μεταβλητές ίσως να μπορεί να λογιστεί ως αντικείμενο, που θα αλληλεπιδρούμε με αυτό και θα διατηρεί μια κατάσταση. Όμως δεν έχει τις δυνατότητες ενός αντικειμένου, και κύρια είναι ότι δεν μπορεί να "επιστραφεί" με τις τιμές του (αν δούμε δηλαδή ότι οι στατικές είναι οι τιμές του, αυτές που προσδιορίζουν την κατάστασή του).
Προσθήκη: Οι συναρτήσεις Λάμδα άλλαξαν την κατάσταση, με τις στατικές και να γιατί. Ενώ οι στατικές έχουν να κάνουν με την σειρά εκτέλεσης (η συνάρτηση Α έχει άλλο σετ στατικών όταν κληθεί από σημείο κώδικα ενός τμήματος Β από εκείνο το σετ όταν κληθεί από το Γ), οι Λάμδα έχουν συλλάβει μεταβλητές, και μπορούμε να δηλώσουμε και νέες μόνο για την λάμδα, οι οποίες θα παραμένουν με το αντικείμενο, στο περιβάλλον του, και θα συνοδεύουν το αντικείμενο, σαν να ήταν τοπικές μεταβλητές, αλλά κρατούν τις τιμές τους σαν να ήταν στατικές.
Στο παράδειγμα η Φ παράγει μια λάμδα που κρατάει ένα Χ και έναν πίνακα Α(). Φτιάχνουμε τις Α και Β και οι δύο έχουν διαφορετικό Χ και έχουν από έναν πίνακα Α() καθώς και τον κώδικα ως συνάρτηση που μπορούν να εκτελέσουν. Εδώ δεν βλέπουμε να αλλάζει η Χ και ο Πίνακας
Συνάρτηση Φ {
Διάβασε Χ
Πίνακας Α(20)=2
Για ι=1 έως 20 : Α(ι-1)*= ι : Επόμενο ι
=Λάμδα Χ, Α() -> {
Διάβασε Κ
Αν Κ<0 ή Κ>19 τότε Λάθος "Εκτός Ορίου"
=Α(Κ)*Χ
}
}
Α=Φ(5)
Β=Φ(20)
Τύπωσε Α(3), Β(3) \\ 40, 160
Ενώ εδώ η Χ αλλάζει κάθε φορά που καλούμε την Α()
Α=Λάμδα Χ=0 ->{Χ++ : =Χ}
Για Ι=1 έως 10 {
Τύπωσε Α()
}
Οι στατικές έχουν την αξία τους στα Νήματα, όπου εκεί έχουμε διαφορετικό αντικείμενο εκτέλεσης, αλλά στο ίδιο όνομα τμήματος, και είναι ο τρόπος να έχουν ιδιωτικές μεταβλητές.
Οι λάμδα δηλαδή συναρτήσεις έχουν ένα όνομα μιας μεταβλητής (αριθμητικής ή αλφαριθμητικής) και περιέχουν μια συνάρτηση και μια λίστα ιδιωτικών μεταβλητών. Οι ιδιωτικές μεταβλητές μπορούν να αλλαχθούν μόνο από την συνάρτηση που περιέχει η λάμδα (αν και αυτό δεν είναι πάντα ακριβές, επειδή ενδέχεται στη λίστα ιδιωτικών μεταβλητών να έχουμε κάποιο αντικείμενο που υπάρχει μόνο με αναφορά, όπως η Κατάσταση, και να υπάρχει και αλλού η ίδια αναφορά, άρα να υπάρχει πρόσβαση για αλλαγές εκτός της λάμδα).
Θα μπορούσε να δει κανείς τις λάμδα ως αντικείμενα με μια είσοδο και μια έξοδο, την συνάρτηση. Τις λέμε αντικείμενα και όχι απλά προγράμματα, γιατί είναι κινητά, δηλαδή μπορεί η λάμδα να επιστραφεί ως αποτέλεσμα, ή και να δοθεί ως όρισμα σε κάπου αλλού.
Δείτε ένα παράδειγμα με δυο προγράμματα, το ένα έχει τις λάμδα με ιδιωτική μεταβλητή και το άλλο με στατική. Έστω το πρώτο το γράφουμε στο τμήμα Α και το δεύτερο στο τμήμα Β (με Σ Α και με Σ Β ανοίγουμε τον διορθωτή σε κάθε περίπτωση και αντιγράφουμε από την ιστοσελίδα το αντίστοιχο πρόγραμμα)
Τμήμα Βήτα {
Α=Λάμδα Χ=1-> {
=Χ
Χ++
}
Για ι=1 έως 5 { Τύπωσε Α() }
'Η λάμδα Μ παίρνει ένα δικό της Χ με την τρέχουσα τιμή στην Α
Μ=Α
Για ι=1 έως 5 { Τύπωσε Μ() } ' οπότε πάμε από 5...μέχρι 10
\\ εξάγουμε τις Μ και Α
\\ η Α θα πάει στη κορυφή του σωρού τιμών
Βάλε Μ, Α
}
Βήτα
\\ η Διάβασε διαβάζει πάντα από την κορυφή, και το επόμενο γίνεται νέα κορυφή
Διάβασε Α, Μ
Για ι=1 έως 5 { Τύπωσε Α() } ' Συνεχίζει η Α() από 5 έως 10
Για ι=1 έως 5 { Τύπωσε Μ() } ' Συνεχίζει η Μ() από 11 έως 15
Αν ξανά τρέξουμε το Α θα πάρουμε την ίδια απόκριση
Τμήμα Βήτα {
Α=Λάμδα -> {
Στατική Χ=1
=Χ
Χ++
}
Για ι=1 έως 5 { Τύπωσε Α() }
Μ=Α
Για ι=1 έως 5 { Τύπωσε Μ() } '' νέα στατική δίνει από 1..
\\ εξάγουμε τις Μ και Α
\\ η Α θα πάει στη κορυφή του σωρού τιμών
Βάλε Μ, Α
}
Βήτα
\\ η Διάβασε διαβάζει πάντα από την κορυφή, και το επόμενο γίνεται νέα κορυφή
Διάβασε Α, Μ
Για ι=1 έως 5 { Τύπωσε Α() } ' νέα στατική δίνει από 1..
Για ι=1 έως 5 { Τύπωσε Μ() } ' νέα στατική δίνει από 1..
Αν ξανά τρέξουμε το Α δεν θα πάρει νέα τιμή η Χ σε κάθε περίπτωση, οπότε τόσο η Α και Μ εντός της Βήτα όσο και οι Α και Μ εκτός (δηλαδή εντός της Β, αφού λέμε να έχει το τμήμα που κρατάει αυτό το πρόγραμμα όνομα Β), συνολικά τέσσερις στατικές θα συνεχίσουν από εκεί που έμειναν.
Από εδώ και κάτω θα δούμε τον ορισμό του βασικού αντικειμένου, που λέγεται ομάδα στην Μ2000.
2.4 Ορισμός Ομάδας
Το βασικό αντικείμενο της Μ2000 είναι η ομάδα. Η ομάδα μπορεί να έχει από το τίποτα, μέχρι ένα ολόκληρο πρόγραμμα με μεταβλητές, ιδιωτικές και δημόσιες, με τμήματα ιδιωτικά και δημόσια, με ιδιότητες (πάντα δημόσιες) όπου ορίζουμε αν θα διαβάζονται ή θα γράφονται ή και τα δύο, και μπορούμε να βγάζουμε αντίγραφα ή να τη βάλουμε στο σωρό με μια απλή εντολή, να την περνάμε σαν παράμετρο, ή να την επιστρέφουμε σε μια συνάρτηση, ή να δίνει τιμή ή να δέχεται τιμή, Οι μεταβλητές της είναι σαν στατικές μεταβλητές αλλά δεν είναι δεμένες με το αντικείμενο εκτέλεσης, δηλαδή το αντικείμενο στο τερματισμό του τμήματος που το δημιούργησε ή θα επιστραφεί με κάποιο τρόπο ή θα διαγραφεί.
Στο παράδειγμα κατάργησα τη Γενική Α ενώ θα μπορούσα να την αφήσω. (το διόρθωσα το παράδειγμα, έχω βάλει την διάβασε Α στο τμήμα ΚάνεΚάτι και αν η Α δεν πάρει τιμή βγαίνει λάθος. Επίσης η κλήση της ΚάνεΚάτι πρέπει να έχει το όνομα του αντικειμένου Αλφα, δηλαδή Αλφα.ΚάνεΚάτι)
(Αλλαγές από 1/4/2017)
2.1. Η μεταβλητή ως μήνυμα!
Είδαμε ότι με ονόματα τμημάτων/συναρτήσεων μπορούμε να φτιάξουμε κώδικα για συγκεκριμένες εργασίες. Αυτές οι εργασίες γίνονται πάνω σε δεδομένα που γράφουμε με το χέρι, ή που εισάγουμε. Είδαμε την έννοια του προσωρινού, όπου η μεταβλητή που εισάγουμε ένα νούμερο μπορεί να το δώσει σε ένα σωρό τιμών και με τη κλήση του τμήματος να διαβαστεί από το σωρό σε μια άλλη μεταβλητή και να την επεξεργαστούμε. Ας δούμε ένα απλό παράδειγμα, π.χ. στο τμήμα Α
(Σ Α enter)
Εισαγωγή "Αριθμός=",Α
Τμήμα ΚάνεΚάτι {
Διάβασε Κ
Τύπωσε Κ*2
}
ΚάνεΚάτι Α
(πλήκτρο Esc και βγαίνουμε στη γραμμή εργασιών)
Εδώ στο παράδειγμα το τμήμα το ορίζουμε πριν το χρησιμοποιήσουμε. Θα μπορούσαμε να το είχαμε γενικό δηλαδή με Σ Α φτιάχνω αυτό:
Εισαγωγή "Αριθμός=",Α
ΚάνεΚάτι Α
Και με Σ ΚάνεΚάτι
Διάβασε Κ
Τύπωσε Κ*2
(με Esc βγαίνουμε από το διορθωτή)
Το παρακάτω στην έκδοση 9 δεν έχει την ίδια απόκριση, διότι αν πατήσουμε άμεσα το enter δίνει τιμή 0, και επιπλέον δεν δέχεται χαρακτήρες που δεν δίνουν αριθμό. Όμως το πρόγραμμα εκτελείται. Δεν βγαίνει ποτέ το οκ ψευδές.
Αν δώσουμε άμεσα ένα enter τότε βγαίνει λάθος. Για να αποτρέψουμε το λάθος (είναι πιο σύνθετο γιατί πρέπει να αποφασίσουμε τι θα γίνει αν κάποιος δεν δώσει νούμερο. εδώ βλέπουμε δυο δομές, την Επανέλαβε { } Μέχρι, για επανάληψη μέχρι μια συνθήκη να δώσει αληθές και την Δες {} η οποία σταματάει τα λάθη από το να διακόπτουν το πρόγραμμα):
Επανέλαβε {
Δες οκ {
Εισαγωγή "Αριθμός=",Α
}
Αν όχι οκ τότε Τύπωσε
} Μέχρι οκ
Το τμήμα ΚάνεΚάτι πήρε ένα μήνυμα, έναν αριθμό και δουλειά του ήταν να το επεξεργαστεί και εδώ μας τύπωσε τον αριθμό επί 2. Δίνω 20 παίρνω 40.
Παρατηρούμε πως εισάγουμε μια μεταβλητή Α με τιμή και πως την περνάμε στο τμήμα σε μια Κ. Αυτό συμβαίνει γιατί το τμήμα ΚάνεΚάτι δεν μπορεί να διαβάσει την Α εκτός και αν την ορίσουμε ως γενική μεταβλητή (εδώ χωρίς το Επανέλαβε/Δες για το χειρισμό του λάθους)
Γενική Α
Εισαγωγή "Αριθμός=",Α
Τμήμα ΚάνεΚάτι {
Τύπωσε Α*2
}
ΚάνεΚάτι
2.2. Τι είναι Κατάσταση (State);
Παρατηρούμε βέβαια ότι το μήνυμα ήταν για άμεση κατανάλωση! Και βέβαια με χρήση γενικής το τμήμα μας δουλεύει μόνο για την συγκεκριμένη μεταβλητή. Τι γίνεται αν θέλουμε να δώσουμε δυο φορές ένα νούμερο και κάθε φορά το αποτέλεσμα του μηνύματος Α να επιδρά και στο νέο Α.
Δηλαδή ξεκινάω με Α_κατάσταση=10 και δίνω μήνυμα Α=20 και παίρνω 50 και μετά με Α=30 παίρνω 110 (30*2+50) και μετά με Α=40 παίρνω 190 (40*2+110)
Δηλαδή θέλω να μένει η κατάσταση μέσα στο τμήμα με κάποιο τρόπο:
Ξεκινώ με τον πιο απλό που μπορώ να σκεφτώ (δεν πειράζει αυτό, μάλιστα επιβάλλεται όταν δεν έχουμε κατασταλάξει πώς θα πετύχουμε κάτι, στο απλό βρίσκουμε το λάθος πιο γρήγορα)
Γενική Α, Β=10
Τμήμα ΚάνεΚάτι {
Τύπωσε Α*2+Β
Β<=Α*2+Β
}
Επανέλαβε {
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
ΚάνεΚάτι
} Πάντα
Δείτε πως στην Β καταχωρώ με <=. Αν δεν το έκανα αυτό τότε θα καταχωρούσα σε τοπική μεταβλητή Β (ο διερμηνευτής δίνει προτεραιότητα στην δημιουργία τοπικών) και κάθε φορά στα δεξιά θα έχω την Β (γενική με τιμή 10) και το αποτέλεσμα θα πήγαινε στη τοπική Β που θα διαγραφόταν στο τέλος!
Κάθε φορά που καλούμε την ΚάνεΚάτι το αποτέλεσμά της εξαρτάται από την Α που μόλις δώσαμε και την Β που είχε ήδη μια τιμή και ίσως άγνωστη σε μας (π.χ. άλλος έδωσε τα πρώτα νούμερα στο πρόγραμμα, το άλλος δείτε το ως γεγονός, ως κάτι που έφερε την τρέχουσα κατάσταση).
Δηλαδή το μήνυμα που δίνουμε αλλάζει την κατάσταση του τμήματος! Αλλά εδώ για να το πετύχουμε έχουμε γενικές μεταβλητές. Μπορεί να γίνει και με άλλους τρόπους, όπως θα δούμε. Η ιδέα όμως να κρατάμε τη κατάσταση σε ένα τμήμα του προγράμματός μας είναι βασική. Πχ σε ένα παιχνίδι κάπου κρατάμε το σκορ, ακόμα και αν αλλάζουμε επίπεδα, ή πίστες όπως λέμε. Αυτό σημαίνει ότι αποθηκεύουμε τη τρέχουσα κατάσταση του σκορ. Η έννοια της τρέχουσας κατάστασης μαζί με την έννοια της επόμενης κατάστασης, είναι βασικές γιατί όταν σχηματίσουμε για συγκεκριμένο ζήτημα το τι είναι αυτό που "γνωρίζει" το πρόγραμμα ως τρέχουσα κατάσταση και τι επιδιώκουμε να αλλάξει στην νέα κατάσταση τότε και μόνο τότε ξέρουμε τι γίνεται και είναι θέμα επιλογής της υλοποίησης για αυτό.
Οι αλλαγές καταστάσεων δεν γίνονται χωρίς ένα μήνυμα (σε μια μεταβλητή) να δώσει το έναυσμα για αυτό. Έτσι η ροή ενός προγράμματος χαρακτηρίζεται από την χρήση των μηνυμάτων, όπως έχει προγραμματιστεί, αλλά σίγουρα για να πούμε τι ακολουθεί, ποια είναι η νέα κατάσταση, δεν έχει μόνο σημασία το πρόγραμμα αλλά και το τι περιεχόμενο έχει το μήνυμα. Πολλές φορές έχουμε ακούσει ότι με λάθος στοιχεία παίρνουμε λάθος αποφάσεις, και ας ακολουθούμε σωστή μεθοδολογία. Ακριβώς αυτό παρατηρούμε και στο προγραμματισμό. Αν έχουμε δει τη συμπεριφορά ενός προγράμματος και την θεωρούμε σωστή για ένα σύνολο εισαγωγών, δεν σημαίνει ότι είναι ένα σωστό πρόγραμμα για κάθε άλλο σύνολο. και ενδεχομένως να συμβεί να μπει εισαγωγή που δεν είχε υπολογιστεί από τον προγραμματιστή και να έχουμε σφάλμα!
Η κατάσταση λοιπόν ενός τμήματος κώδικα, ας το αναφέρουμε με τον απλό αυτό τρόπο, σχετίζεται και με το πως γράφεται ο κώδικας αλλά και με το τι μεταφέρει, τι τιμές έχει σε μεταβλητές σε κάθε νέα εκτέλεση.
2.3. Στατικές Μεταβλητές
Μια άλλη προσέγγιση έχει να κάνει με την έννοια της στατικής μεταβλητής:
Η Μ2000 μπορεί να φτιάχνει στατικές μεταβλητές σε τμήματα και συναρτήσεις (και τελεστές, είδος συναρτήσεων για ομάδες). Στατικές μπορούν να είναι απλές μεταβλητές όπως Α ή Α$ ή Α%, όχι πίνακες δηλαδή, αν και υπάρχει αντικείμενο πίνακας που μπορεί να περαστεί με αναφορά σε μια απλή μεταβλητή αλλά δεν θα το δούμε αυτό εδώ.
Γενική Α
Τμήμα ΚάνεΚάτι {
Στατική Β=10
Τύπωσε Α*2+Β
Β=Α*2+Β
}
Επανέλαβε {
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
ΚάνεΚάτι
} Πάντα
Τώρα έχουμε μια ίδια απόκριση. Η Β θα γίνει 10 μια φορά, δηλαδή το =10 δίνει την αρχική τιμή. Την επόμενη που θα κληθεί η ΚάνεΚάτι θα δει ο διερμηνευτής ότι υπάρχει η Β και δεν θα της δώσει την αρχική τιμή. Η τιμή της Β φυλάσσεται χώρια, και παρόλο που το τμήμα θα τερματίσει και όλες οι τοπικές (λέγονται και αυτόματες) θα διαγραφούν, οι στατικές θα παραμείνουν στο αντικείμενο εκτέλεσης του τμήματος, και μόλις και αυτό τερματίσει όλες οι στατικές θα παραμείνουν στο σύστημα.
Στο παράδειγμα μπορούμε να κατανοήσουμε την αποθήκευση της στατικής με δυο τρόπους:
1. Τρέχουμε το τμήμα που έχουμε γράψει το παράδειγμα, έστω Α και δίνουμε διαδοχικά την ίδια τιμή έστω 12 στην εισαγωγή αριθμού.
2. Βγαίνουμε εκτός μετά και ξαναμπαίνουμε στο τμήμα που θα δημιουργήσει το τμήμα ΚάνεΚάτι, και τότε θα βρεθεί πάλι η στατική με τη τελευταία τιμή. Δηλαδή παρόλο που δεν θα υπάρχει το τμήμα ΚάνεΚάτι εντός του τμήματος (επειδή έχουμε βγει από αυτό και διαγράφτηκε), οι στατικές θα παραμείνουν αποθηκευμένες και θα αποδοθούν την επόμενη φορά που θα το δημιουργήσουμε και θα το καλέσουμε.
Για να σβήσουν οι στατικές απαιτείται η εντολή Καθαρό, ή αν θέλουμε να σβήσουμε όλα τα τμήματα η εντολή Νέο.
Για τα δυο τελευταία παραδείγματα φαίνεται να έχουν την ίδια λειτουργία, όσο στο δεύτερο με την στατική δεν διακόψουμε και εκκινήσουμε! Στη δεύτερη εκκίνηση αυτό που λείπει είναι η αρχικοποίηση της στατικής, η οποία δεν γίνεται γιατί ήδη υπάρχει! Η απουσία "αλλαγής" τιμής είναι και αυτή με την ίδια έννοια ταυτόσιμη με την παρουσία αλλαγής, άρα και αυτό αποτελεί μήνυμα ως έναυσμα για αλλαγή κατάστασης.
Δείτε ότι το πέρασμα νέας τιμής έγινε με απλό =. Δεν είναι απλά τοπική η στατική μεταβλητή, αλλά και εντελώς, είναι ιδιωτική! Δεν γίνεται να διαβαστεί από πουθενά αλλού. Ουσιαστικά δεν είναι "δεμένη" με το τμήμα αλλά με το αντικείμενο που τρέχει το τμήμα, δηλαδή με εκείνο που το καλεί!
Έτσι αν έχουμε ένα γενικό τμήμα και έχει στατική μεταβλητή τότε για κάθε κλήση του από διαφορετικό τμήμα θα έχει διαφορετικό σετ στατικών.
Εδώ αξίζει να σημειωθεί ότι σε άλλες γλώσσες οι στατικές έχουν τον ίδιο χώρο, άρα δίνουν την ίδια τιμή ανεξάρτητα από που κλήθηκε η συνάρτηση που τις περιέχει. Στη Μ2000 η κλήση συνάρτησης σχετίζεται με τη σειρά εκτέλεσης που καλούμε, άρα θέλουμε οι στατικές να έχουν να κάνουν με αυτό και όχι με κάποιο άλλο.
Ένα τμήμα που έχει στατικές μεταβλητές ίσως να μπορεί να λογιστεί ως αντικείμενο, που θα αλληλεπιδρούμε με αυτό και θα διατηρεί μια κατάσταση. Όμως δεν έχει τις δυνατότητες ενός αντικειμένου, και κύρια είναι ότι δεν μπορεί να "επιστραφεί" με τις τιμές του (αν δούμε δηλαδή ότι οι στατικές είναι οι τιμές του, αυτές που προσδιορίζουν την κατάστασή του).
Προσθήκη: Οι συναρτήσεις Λάμδα άλλαξαν την κατάσταση, με τις στατικές και να γιατί. Ενώ οι στατικές έχουν να κάνουν με την σειρά εκτέλεσης (η συνάρτηση Α έχει άλλο σετ στατικών όταν κληθεί από σημείο κώδικα ενός τμήματος Β από εκείνο το σετ όταν κληθεί από το Γ), οι Λάμδα έχουν συλλάβει μεταβλητές, και μπορούμε να δηλώσουμε και νέες μόνο για την λάμδα, οι οποίες θα παραμένουν με το αντικείμενο, στο περιβάλλον του, και θα συνοδεύουν το αντικείμενο, σαν να ήταν τοπικές μεταβλητές, αλλά κρατούν τις τιμές τους σαν να ήταν στατικές.
Στο παράδειγμα η Φ παράγει μια λάμδα που κρατάει ένα Χ και έναν πίνακα Α(). Φτιάχνουμε τις Α και Β και οι δύο έχουν διαφορετικό Χ και έχουν από έναν πίνακα Α() καθώς και τον κώδικα ως συνάρτηση που μπορούν να εκτελέσουν. Εδώ δεν βλέπουμε να αλλάζει η Χ και ο Πίνακας
Συνάρτηση Φ {
Διάβασε Χ
Πίνακας Α(20)=2
Για ι=1 έως 20 : Α(ι-1)*= ι : Επόμενο ι
=Λάμδα Χ, Α() -> {
Διάβασε Κ
Αν Κ<0 ή Κ>19 τότε Λάθος "Εκτός Ορίου"
=Α(Κ)*Χ
}
}
Α=Φ(5)
Β=Φ(20)
Τύπωσε Α(3), Β(3) \\ 40, 160
Ενώ εδώ η Χ αλλάζει κάθε φορά που καλούμε την Α()
Α=Λάμδα Χ=0 ->{Χ++ : =Χ}
Για Ι=1 έως 10 {
Τύπωσε Α()
}
Οι στατικές έχουν την αξία τους στα Νήματα, όπου εκεί έχουμε διαφορετικό αντικείμενο εκτέλεσης, αλλά στο ίδιο όνομα τμήματος, και είναι ο τρόπος να έχουν ιδιωτικές μεταβλητές.
Οι λάμδα δηλαδή συναρτήσεις έχουν ένα όνομα μιας μεταβλητής (αριθμητικής ή αλφαριθμητικής) και περιέχουν μια συνάρτηση και μια λίστα ιδιωτικών μεταβλητών. Οι ιδιωτικές μεταβλητές μπορούν να αλλαχθούν μόνο από την συνάρτηση που περιέχει η λάμδα (αν και αυτό δεν είναι πάντα ακριβές, επειδή ενδέχεται στη λίστα ιδιωτικών μεταβλητών να έχουμε κάποιο αντικείμενο που υπάρχει μόνο με αναφορά, όπως η Κατάσταση, και να υπάρχει και αλλού η ίδια αναφορά, άρα να υπάρχει πρόσβαση για αλλαγές εκτός της λάμδα).
Θα μπορούσε να δει κανείς τις λάμδα ως αντικείμενα με μια είσοδο και μια έξοδο, την συνάρτηση. Τις λέμε αντικείμενα και όχι απλά προγράμματα, γιατί είναι κινητά, δηλαδή μπορεί η λάμδα να επιστραφεί ως αποτέλεσμα, ή και να δοθεί ως όρισμα σε κάπου αλλού.
Δείτε ένα παράδειγμα με δυο προγράμματα, το ένα έχει τις λάμδα με ιδιωτική μεταβλητή και το άλλο με στατική. Έστω το πρώτο το γράφουμε στο τμήμα Α και το δεύτερο στο τμήμα Β (με Σ Α και με Σ Β ανοίγουμε τον διορθωτή σε κάθε περίπτωση και αντιγράφουμε από την ιστοσελίδα το αντίστοιχο πρόγραμμα)
Τμήμα Βήτα {
Α=Λάμδα Χ=1-> {
=Χ
Χ++
}
Για ι=1 έως 5 { Τύπωσε Α() }
'Η λάμδα Μ παίρνει ένα δικό της Χ με την τρέχουσα τιμή στην Α
Μ=Α
Για ι=1 έως 5 { Τύπωσε Μ() } ' οπότε πάμε από 5...μέχρι 10
\\ εξάγουμε τις Μ και Α
\\ η Α θα πάει στη κορυφή του σωρού τιμών
Βάλε Μ, Α
}
Βήτα
\\ η Διάβασε διαβάζει πάντα από την κορυφή, και το επόμενο γίνεται νέα κορυφή
Διάβασε Α, Μ
Για ι=1 έως 5 { Τύπωσε Α() } ' Συνεχίζει η Α() από 5 έως 10
Για ι=1 έως 5 { Τύπωσε Μ() } ' Συνεχίζει η Μ() από 11 έως 15
Αν ξανά τρέξουμε το Α θα πάρουμε την ίδια απόκριση
Τμήμα Βήτα {
Α=Λάμδα -> {
Στατική Χ=1
=Χ
Χ++
}
Για ι=1 έως 5 { Τύπωσε Α() }
Μ=Α
Για ι=1 έως 5 { Τύπωσε Μ() } '' νέα στατική δίνει από 1..
\\ εξάγουμε τις Μ και Α
\\ η Α θα πάει στη κορυφή του σωρού τιμών
Βάλε Μ, Α
}
Βήτα
\\ η Διάβασε διαβάζει πάντα από την κορυφή, και το επόμενο γίνεται νέα κορυφή
Διάβασε Α, Μ
Για ι=1 έως 5 { Τύπωσε Α() } ' νέα στατική δίνει από 1..
Για ι=1 έως 5 { Τύπωσε Μ() } ' νέα στατική δίνει από 1..
Αν ξανά τρέξουμε το Α δεν θα πάρει νέα τιμή η Χ σε κάθε περίπτωση, οπότε τόσο η Α και Μ εντός της Βήτα όσο και οι Α και Μ εκτός (δηλαδή εντός της Β, αφού λέμε να έχει το τμήμα που κρατάει αυτό το πρόγραμμα όνομα Β), συνολικά τέσσερις στατικές θα συνεχίσουν από εκεί που έμειναν.
Από εδώ και κάτω θα δούμε τον ορισμό του βασικού αντικειμένου, που λέγεται ομάδα στην Μ2000.
2.4 Ορισμός Ομάδας
Το βασικό αντικείμενο της Μ2000 είναι η ομάδα. Η ομάδα μπορεί να έχει από το τίποτα, μέχρι ένα ολόκληρο πρόγραμμα με μεταβλητές, ιδιωτικές και δημόσιες, με τμήματα ιδιωτικά και δημόσια, με ιδιότητες (πάντα δημόσιες) όπου ορίζουμε αν θα διαβάζονται ή θα γράφονται ή και τα δύο, και μπορούμε να βγάζουμε αντίγραφα ή να τη βάλουμε στο σωρό με μια απλή εντολή, να την περνάμε σαν παράμετρο, ή να την επιστρέφουμε σε μια συνάρτηση, ή να δίνει τιμή ή να δέχεται τιμή, Οι μεταβλητές της είναι σαν στατικές μεταβλητές αλλά δεν είναι δεμένες με το αντικείμενο εκτέλεσης, δηλαδή το αντικείμενο στο τερματισμό του τμήματος που το δημιούργησε ή θα επιστραφεί με κάποιο τρόπο ή θα διαγραφεί.
Στο παράδειγμα κατάργησα τη Γενική Α ενώ θα μπορούσα να την αφήσω. (το διόρθωσα το παράδειγμα, έχω βάλει την διάβασε Α στο τμήμα ΚάνεΚάτι και αν η Α δεν πάρει τιμή βγαίνει λάθος. Επίσης η κλήση της ΚάνεΚάτι πρέπει να έχει το όνομα του αντικειμένου Αλφα, δηλαδή Αλφα.ΚάνεΚάτι)
(Επίσης αν βάλουμε τη Γενική Α στην αρχή τότε η Α εντός της ΚάνεΚάτι δεν θα είναι η γενική Α αλλά η τοπική Α που φτιάχνει ο διερμηνευτής. Αν στην κλήση δεν δώσουμε τη τιμή της Α ή κάποια τιμή ως όρισμα τότε στην Διάβασε Α αν δεν υπάρχει τιμή στο σωρό τιμών θα βγει λάθος, επειδή ο διερμηνευτής δεν μπορεί να αρχικοποιήσει την Α). Η επανάλαβε γράφεται και χωρίς αγκύλες (αλλά τις βάζει ο διερμηνευτής - τις λογαριάζει κατά μια έννοια).
Ομάδα Αλφα {
Β=10
Τμήμα ΚάνεΚάτι {
Διάβασε Α
Τύπωσε Α*2+.Β
.Β<=Α*2+.Β
}
}
Επανέλαβε
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
Αλφα.ΚάνεΚάτι Α
Πάντα
Δείτε τώρα ότι στο τμήμα ΚάνεΚάτι που ανήκει πια στο Άλφα και όχι άμεσα στο τμήμα που είναι το αντικείμενο έχουμε τη Β σαν να είναι γενική αλλά με μια τελεία. Αυτή η τελεία δηλώνει το Αυτό (το αντικείμενο). Αντί να γράψω αυτό (που δουλεύει και έτσι):
Ομάδα Αλφα {
Β=10
Τμήμα ΚάνεΚάτι {
Διάβασε Α
Τύπωσε Α*2+Αυτό.Β
Αυτό.Β<=Α*2+Αυτό.Β
}
}
Έχω εξαιρέσει τη λέξη Αυτό και δείτε τώρα πιο μαζεμένο το πρόγραμμα (εδώ το ΚάνεΚάτι δεν διαβάζει παράμετρο):
Ομάδα Αλφα {
Β=10, Α
Τμήμα ΚάνεΚάτι {
Τύπωσε .Α*2+.Β
.Β+=.Α*2
}
}
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
Αλφα.ΚάνεΚάτι Α
Πάντα
Δείτε τώρα ότι στο τμήμα ΚάνεΚάτι που ανήκει πια στο Άλφα και όχι άμεσα στο τμήμα που είναι το αντικείμενο έχουμε τη Β σαν να είναι γενική αλλά με μια τελεία. Αυτή η τελεία δηλώνει το Αυτό (το αντικείμενο). Αντί να γράψω αυτό (που δουλεύει και έτσι):
Ομάδα Αλφα {
Β=10
Τμήμα ΚάνεΚάτι {
Διάβασε Α
Τύπωσε Α*2+Αυτό.Β
Αυτό.Β<=Α*2+Αυτό.Β
}
}
Έχω εξαιρέσει τη λέξη Αυτό και δείτε τώρα πιο μαζεμένο το πρόγραμμα (εδώ το ΚάνεΚάτι δεν διαβάζει παράμετρο):
Ομάδα Αλφα {
Β=10, Α
Τμήμα ΚάνεΚάτι {
Τύπωσε .Α*2+.Β
.Β+=.Α*2
}
}
Επανέλαβε {
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
ΚάνεΚάτι
} Πάντα
Τώρα έχω βγάλει τη γενική Α και απευθείας γράφω στην Α της Ομάδας. Δείτε ακόμα ότι την Β την αλλάζω χωρίς το <= αλλά με το += (υπάρχουν τα -= *= /= αλλά και τα ++ -- και τα -! αλλαγή προσίμου και ~ αναστροφή - κάνει το Αληθές Ψευδές και το ανάποδο). Αυτές οι συντομεύσεις δουλεύουν για κάθε τύπο μεταβλητής και για πίνακες. (δείτε επίσης ότι το όνομα της ομάδας δεν έχει τόνο ενώ το χρησιμοποιώ και με τόνο)
Ας μαζέψουμε το πρόγραμμα χωρίς να ξαναγράψουμε την ομάδα και χωρίς εισαγωγή και επανάληψη:
Για Άλφα {
.Α=20
.ΚάνεΚάτι
.Α=30
.ΚάνεΚάτι
.Α=40
.ΚάνεΚάτι
}
ή με επανάληψη τύπου Ενώ (Όσο την λένε στη Γλώσσα του σχολείου). Εδώ έχω τα στοιχεία σε σειρά, άρα μπορώ με άνεση να βάλω όσα θέλω αντί να τα πληκτρολογώ ένα προς ένα, με ερώτηση και με έλεγχο λάθους! Είναι περιττά! Φτιάχνω νέο σωρό γιατί μπορεί να έχει κάτι ο τρέχον και έχω την Ενώ να διαβάζει ενώ δεν είναι κενός ο σωρός. Στην έξοδο από το Σωρός Νέος {} ο προηγούμενος σωρός τιμών παίρνει ξανά τη θέση του.
Για Άλφα {
Σωρός Νέος {
Σειρά 20, 30, 40
Ενώ όχι κενό {
Διάβασε .Α
.ΚάνεΚάτι
}
}
}
Ας δούμε όμως πως μεταφέρουμε ένα αντικείμενο Ομάδα! (αφού είδαμε ότι ένα αντικείμενο, έχει τη δυνατότητα να μεταφέρεται, δηλαδή να γίνεται όρισμα ή να γίνεται επιστροφή τιμής)
Το παράδειγμα περιλαμβάνει δυνατότητες από την 8.4 και πάνω έκδοση, και ειδικότερα το να έχουμε ομάδες με αξία, σαν μεταβλητές, και ιδιότητες που είναι εσωτερικά ομάδες (μπορούν να έχουν άλλες ιδιότητες, τμήματα, συναρτήσεις), όπως να έχουν ή Αξία ή να παίρνουν τιμή μέρος {Θέσε} ή και τα δύο. Εδώ η ιδιότητα Α στο αντικείμενο Αλφα παίρνει μόνο τιμή, ενώ διαβάζεται από το τμήμα ΚάνεΚάτι με άλλο όνομα (το οποίο δεν είναι φανερό έξω από την ομάδα).
Ομάδα Αλφα {
Ιδιωτικό:
Β=10
Δημόσιο:
\\ οι ιδιότητες είναι ομάδες
\\ εδώ η Α έχει μόνο εισαγωγή, ενώ εξαγωγή έχει το αντικείμενό της
\\ το οποίο δεν είναι χρήσιμο
\\ μπορούμε να δίνουμε και αρχική τιμή
Ιδιότητα Α {Θέσε}=10
Τμήμα ΚάνεΚάτι {
\\ η ιδιότητα Α φτιάχνει μια μεταβλητή [Α] και την διαβάζουμε ως .[Α]
\\ ετσί ενώ δεν διαβάζεται έξω από την ομάδα, μέσα την διαβάζουμε!
Τύπωσε .[Α]*2+.Β
.Β+=.[Α]*2
}
Αξία {
=.Β
}
}
Αλφα.Α=12
Αλφα.ΚάνεΚάτι \\ 34
Τύπωσε Αλφα \\ τυπώνει 34, (λειτουργεί η συνάρτηση Αξία)
Αλφα.Α=12
Αλφα.ΚάνεΚάτι \\58
Τύπωσε Αλφα \\ τυπώνει 58, (λειτουργεί η συνάρτηση Αξία)
Τύπωσε Τύπος$(Άλφα.Α) \\ λέει Group δηλαδή ομάδα, η ιδιότητα Α δεν έχει τιμή να δώσει
Τύπωσε Άλφα>20 \\ η Άλφα φαίνεται σαν αριθμός, γιατί έχουμε δώσει Αξία { =.Β }
Δες Οκ {
Αλφα=100
}
Αν όχι Οκ τότε Τύπωσε Λάθος$
\\ βγαίνει μήνυμα "Χρειάζομαι μια ομάδα από τη δεξιά έκφραση"
\\ δεν έχουμε μέρος Θέσε για να δώσουμε τιμή στην ομάδα, οπότε περιμένει μια άλλη ομάδα
\\ για να κάνει συγχώνευση!
Τύπωσε Έγκυρο(Άλφα.Β) \\ 0 δεν είναι γιατί η Β είναι ιδιωτική
\\ εδώ είναι το ζουμί!
Τμήμα Βήτα {
Διάβασε Χ \\ η Χ είναι απλά μια αριθμητική μεταβλητή και όχι μια ομάδα
Τύπωσε Χ \\ 58
}
Βήτα Άλφα \\ επειδή έχει Αξία η Άλφα μεταφέρεται την Αξία της {=.Β}
Τμήμα Βήτα1 {
Διάβασε ΜιαΟμάδα \\ διαβάζει αντίγραφο
Τύπωσε ΜιαΟμάδα \\ 58
\\ όμως εδώ έχουμε την ομάδα
ΜιαΟμάδα.ΚάνεΚάτι \\82
Τύπωσε ΜιαΟμάδα \\ 82
}
Βήτα1 Ομάδα(Άλφα) \\ αν η ομάδα δεν είχε Αξία δεν θα χρειάζονταν η Συνάρτηση Ομάδα()
Τύπωσε Άλφα, "58" \\ παραμένει στο 58
Τμήμα Βήτα2 {
Διάβασε &ΜιαΟμάδα \\ διαβάζει την ομάδα με αναφορά
Τύπωσε ΜιαΟμάδα \\ 58
\\ όμως εδώ έχουμε την ομάδα
ΜιαΟμάδα.ΚάνεΚάτι \\ 82
Τύπωσε ΜιαΟμάδα \\ 82
}
Βήτα2 &Άλφα
Τύπωσε Άλφα, "82" \\ τώρα έχει αλλάξει!
Με απλό τρόπο είδαμε στα τμήματα Βήτα1 και Βήτα2 με ένα πέρασμα ονόματος να προωθούμε όχι μόνο τιμή αλλά και λειτουργικότητα. Στη δεύτερη περίπτωση οι αλλαγές επιστρέφονται στον καλούντα (πέρασμα με αναφορά), στην πρώτη όχι (πέρασμα με τιμή, όλη την ομάδα). Άρα πράγματι μετακινήσαμε το αντικείμενο και με αντίγραφο και όπως ήταν. Εδώ δεν είδαμε την επιστροφή από συνάρτηση. Και αυτό γίνεται! Επειδή μάλιστα έχει Αξία η Άλφα το {=.Β} αν η Άλφα ήταν σε συνάρτηση τότε θα την επιστρέφαμε ως =Ομάδα(Άλφα) με την συνάρτηση Ομάδα() η οποία διαβάζει το αντικείμενο, δεν εκτελεί την όποια Αξία (είναι συνάρτηση για το αντικείμενο) και το μαζεύει ως αντίγραφο αυτού και το παραδίδει ως ανώνυμο αντικείμενο.
Επίσης να δούμε ότι η αναφορά όταν παιρνάμε με το & την Άλφα στην ουσία παιρνάμε μια ισχνή αναφορά (ένα αλφαριθμητικό που λέει το όνομα που χρειάζεται για να την βρει η Διάβασε και να την συνδέσει με το όνομα που θέλουμε). Αν την επιστρέφαμε ως μια τιμή (αν και είναι αλφαριθμητικό και θα βγει λάθος σε μια αριθμητική συνάρτηση), και έστω ότι δεν έβγαινε λάθος τότε η ισχνή αναφορά θα έδειχνει αυτό που δεν θα υπήρχε (Αφού η συνάρτηση στην επιστροφή σβήνει ότι φτιάχνει, εκτός από την τιμή που γυρνάει). Ως όρισμα με αναφορά, επειδή η Διάβασε ενώνει την τοπική με αυτή που δίνουμε με αναφορά, κατά τη χρήση χρησιμοποιεί την εξωτερική, άρα αυτό που θα καταστρέψει στο τέλος εκτέλεσης της συνάρτησης είναι η ένωση, του ονόματος και όχι αυτό που αναφέρει η ένωση!
Από την 9η έκδοση οι ομάδες μπορούν να δίνουν δείκτη σε μεταβλητή και αυτή η μεταβλητή να χρησιμοποιείται ως να είναι η ομάδα. Η επώνυμη ομάδα πχ Αλφα δεν είναι δείκτης σε ομάδα (εσωτερικά όντως είναι δείκτης). Έτσι όταν ορίσουμε μια νέα μεταβλητή έστω Βήτα με το Βήτα=Αλφα τότε παράγεται αντίγραφο στο Βήτα. Με το Μ->Αλφα θα πάρουμε δείκτη της Αλφα και το Ζ=Μ θα κάνει αντιγραφή του δείκτη. Δείτε όμως ότι όπως υπάρχουν δυο τύποι ομάδων, οι επώνυμες και οι πτητικές ή ανώνυμες, έτσι και οι δείκτες εσωτερικά είναι δυο ειδών αλλά είναι αθέατοι στο χρήστη. Όμως υπάρχουν συνέπειες στην χρήση τους. Πχ το Μ παραπάνω δείχνει το Α ως αναφορά στο Α,και αν το Α χαθεί τότε το Μ μένει με ένα δείκτη που δεν δείχνει κάτι! Ουσιαστικά ο δείκτης αυτός είναι ισχνή αναφορά, οπότε γίνεται έλεγχος πριν την χρήση του. Αν δώσουμε Μ->(Αλφα) τότε το (Αλφα) θα είναι αντίγραφο της Άλφα ως ανώνυμη ομάδα (πτητική, γιατί μπορεί να μετακινηθεί), και το Μ έχει γνήσιο δείκτη. Εδώ η ζωή της ομάδας εξαρτιέται από τον αριθμό των δεικτών προς αυτήν. Όταν ο τελευταίος δείκτης διαγραφεί τότε θα πάρει εντολή το σύστημα να διαγράψει την ομάδα. Με αυτό το σύστημα μπορούμε να έχουμε δείκτες σε ομάδες που είναι σε πίνακες (ενώ δεν μπορούμε να έχουμε αναφορά σε στοιχεία πίνακα, μπορούμε να έχουμε γνήσιους δείκτες). Έτσι αν έχουμε ένα πίνακα Α() και δώσουμε αυτό Α(3)=Αλφα, θα μπει ένα αντίγραφο του Αλφα στο Α(3), και μετά αυτό Μ->Α(3) θα έχουμε ένα δείκτη Μ να δείχνει σε αυτό το αντίγραφο. Αν δώσουμε ξανά το Α(3)=Άλφα τότε το Μ θα δείχνει τη παλιά τιμή του Α(3).
Σε αντικείμενα σε άλλες γλώσσες ξεχωρίζει ο κώδικας (λέγεται Interface) από τα δεδομένα (λέγονται instance). Μάλιστα μπορούν να υπάρχουν πολλαπλά Interface για την ίδια παρουσία (instance).
Στη Μ2000 η ομάδα φέρει τον κώδικα και δεδομένα μαζί και δεν υπάρχει τύπος ή interface εκτός από το βασικό αυτό της Ομάδας.Το τμήμα Βήτα2 θα μπορούσε να πάρει οποιοδήποτε ομάδα. Βέβαια αφού χρησιμοποιούμε συγκεκριμένα ονόματα που σχετίζονται με την ομάδα σημαίνει ότι υλοποιούμε την χρήση ενός interface, ενός προσαρμογέα δηλαδή που συνομιλεί με το αντικείμενο. Απλά ορισμένες γλώσσες κάνουν έλεγχο τύπου πριν βγάλουν εκτελέσιμο κώδικα, ενώ στη Μ2000 μπορούμε να εφαρμόσουμε όποια στρατηγική θέλουμε στο πώς θα χειριστούμε την οποιαδήποτε ομάδα περάσουμε στο Βήτα2. Στις νεότερες εκδόσεις της γλώσσας μπορούμε να ορίσουμε τύπο ομάδας ώστε όταν ζητάμε τιμή γιαπαράμετρο σε μια συνάρτηση ή ένα τμήμα να ορίζουμε το όνομα του τύπου. Μια ομάδα μπορεί να έχει περισσότερους από ένα τύπο:
Εισαγωγή "Αριθμός (0/enter για Έξοδος)=",Α
Αν Α=0 τότε έξοδος
ΚάνεΚάτι
} Πάντα
Τώρα έχω βγάλει τη γενική Α και απευθείας γράφω στην Α της Ομάδας. Δείτε ακόμα ότι την Β την αλλάζω χωρίς το <= αλλά με το += (υπάρχουν τα -= *= /= αλλά και τα ++ -- και τα -! αλλαγή προσίμου και ~ αναστροφή - κάνει το Αληθές Ψευδές και το ανάποδο). Αυτές οι συντομεύσεις δουλεύουν για κάθε τύπο μεταβλητής και για πίνακες. (δείτε επίσης ότι το όνομα της ομάδας δεν έχει τόνο ενώ το χρησιμοποιώ και με τόνο)
Ας μαζέψουμε το πρόγραμμα χωρίς να ξαναγράψουμε την ομάδα και χωρίς εισαγωγή και επανάληψη:
Για Άλφα {
.Α=20
.ΚάνεΚάτι
.Α=30
.ΚάνεΚάτι
.Α=40
.ΚάνεΚάτι
}
ή με επανάληψη τύπου Ενώ (Όσο την λένε στη Γλώσσα του σχολείου). Εδώ έχω τα στοιχεία σε σειρά, άρα μπορώ με άνεση να βάλω όσα θέλω αντί να τα πληκτρολογώ ένα προς ένα, με ερώτηση και με έλεγχο λάθους! Είναι περιττά! Φτιάχνω νέο σωρό γιατί μπορεί να έχει κάτι ο τρέχον και έχω την Ενώ να διαβάζει ενώ δεν είναι κενός ο σωρός. Στην έξοδο από το Σωρός Νέος {} ο προηγούμενος σωρός τιμών παίρνει ξανά τη θέση του.
Για Άλφα {
Σωρός Νέος {
Σειρά 20, 30, 40
Ενώ όχι κενό {
Διάβασε .Α
.ΚάνεΚάτι
}
}
}
Ας δούμε όμως πως μεταφέρουμε ένα αντικείμενο Ομάδα! (αφού είδαμε ότι ένα αντικείμενο, έχει τη δυνατότητα να μεταφέρεται, δηλαδή να γίνεται όρισμα ή να γίνεται επιστροφή τιμής)
Το παράδειγμα περιλαμβάνει δυνατότητες από την 8.4 και πάνω έκδοση, και ειδικότερα το να έχουμε ομάδες με αξία, σαν μεταβλητές, και ιδιότητες που είναι εσωτερικά ομάδες (μπορούν να έχουν άλλες ιδιότητες, τμήματα, συναρτήσεις), όπως να έχουν ή Αξία ή να παίρνουν τιμή μέρος {Θέσε} ή και τα δύο. Εδώ η ιδιότητα Α στο αντικείμενο Αλφα παίρνει μόνο τιμή, ενώ διαβάζεται από το τμήμα ΚάνεΚάτι με άλλο όνομα (το οποίο δεν είναι φανερό έξω από την ομάδα).
Ομάδα Αλφα {
Ιδιωτικό:
Β=10
Δημόσιο:
\\ οι ιδιότητες είναι ομάδες
\\ εδώ η Α έχει μόνο εισαγωγή, ενώ εξαγωγή έχει το αντικείμενό της
\\ το οποίο δεν είναι χρήσιμο
\\ μπορούμε να δίνουμε και αρχική τιμή
Ιδιότητα Α {Θέσε}=10
Τμήμα ΚάνεΚάτι {
\\ η ιδιότητα Α φτιάχνει μια μεταβλητή [Α] και την διαβάζουμε ως .[Α]
\\ ετσί ενώ δεν διαβάζεται έξω από την ομάδα, μέσα την διαβάζουμε!
Τύπωσε .[Α]*2+.Β
.Β+=.[Α]*2
}
Αξία {
=.Β
}
}
Αλφα.Α=12
Αλφα.ΚάνεΚάτι \\ 34
Τύπωσε Αλφα \\ τυπώνει 34, (λειτουργεί η συνάρτηση Αξία)
Αλφα.Α=12
Αλφα.ΚάνεΚάτι \\58
Τύπωσε Αλφα \\ τυπώνει 58, (λειτουργεί η συνάρτηση Αξία)
Τύπωσε Τύπος$(Άλφα.Α) \\ λέει Group δηλαδή ομάδα, η ιδιότητα Α δεν έχει τιμή να δώσει
Τύπωσε Άλφα>20 \\ η Άλφα φαίνεται σαν αριθμός, γιατί έχουμε δώσει Αξία { =.Β }
Δες Οκ {
Αλφα=100
}
Αν όχι Οκ τότε Τύπωσε Λάθος$
\\ βγαίνει μήνυμα "Χρειάζομαι μια ομάδα από τη δεξιά έκφραση"
\\ δεν έχουμε μέρος Θέσε για να δώσουμε τιμή στην ομάδα, οπότε περιμένει μια άλλη ομάδα
\\ για να κάνει συγχώνευση!
Τύπωσε Έγκυρο(Άλφα.Β) \\ 0 δεν είναι γιατί η Β είναι ιδιωτική
\\ εδώ είναι το ζουμί!
Τμήμα Βήτα {
Διάβασε Χ \\ η Χ είναι απλά μια αριθμητική μεταβλητή και όχι μια ομάδα
Τύπωσε Χ \\ 58
}
Βήτα Άλφα \\ επειδή έχει Αξία η Άλφα μεταφέρεται την Αξία της {=.Β}
Τμήμα Βήτα1 {
Διάβασε ΜιαΟμάδα \\ διαβάζει αντίγραφο
Τύπωσε ΜιαΟμάδα \\ 58
\\ όμως εδώ έχουμε την ομάδα
ΜιαΟμάδα.ΚάνεΚάτι \\82
Τύπωσε ΜιαΟμάδα \\ 82
}
Βήτα1 Ομάδα(Άλφα) \\ αν η ομάδα δεν είχε Αξία δεν θα χρειάζονταν η Συνάρτηση Ομάδα()
Τύπωσε Άλφα, "58" \\ παραμένει στο 58
Τμήμα Βήτα2 {
Διάβασε &ΜιαΟμάδα \\ διαβάζει την ομάδα με αναφορά
Τύπωσε ΜιαΟμάδα \\ 58
\\ όμως εδώ έχουμε την ομάδα
ΜιαΟμάδα.ΚάνεΚάτι \\ 82
Τύπωσε ΜιαΟμάδα \\ 82
}
Βήτα2 &Άλφα
Τύπωσε Άλφα, "82" \\ τώρα έχει αλλάξει!
Με απλό τρόπο είδαμε στα τμήματα Βήτα1 και Βήτα2 με ένα πέρασμα ονόματος να προωθούμε όχι μόνο τιμή αλλά και λειτουργικότητα. Στη δεύτερη περίπτωση οι αλλαγές επιστρέφονται στον καλούντα (πέρασμα με αναφορά), στην πρώτη όχι (πέρασμα με τιμή, όλη την ομάδα). Άρα πράγματι μετακινήσαμε το αντικείμενο και με αντίγραφο και όπως ήταν. Εδώ δεν είδαμε την επιστροφή από συνάρτηση. Και αυτό γίνεται! Επειδή μάλιστα έχει Αξία η Άλφα το {=.Β} αν η Άλφα ήταν σε συνάρτηση τότε θα την επιστρέφαμε ως =Ομάδα(Άλφα) με την συνάρτηση Ομάδα() η οποία διαβάζει το αντικείμενο, δεν εκτελεί την όποια Αξία (είναι συνάρτηση για το αντικείμενο) και το μαζεύει ως αντίγραφο αυτού και το παραδίδει ως ανώνυμο αντικείμενο.
Επίσης να δούμε ότι η αναφορά όταν παιρνάμε με το & την Άλφα στην ουσία παιρνάμε μια ισχνή αναφορά (ένα αλφαριθμητικό που λέει το όνομα που χρειάζεται για να την βρει η Διάβασε και να την συνδέσει με το όνομα που θέλουμε). Αν την επιστρέφαμε ως μια τιμή (αν και είναι αλφαριθμητικό και θα βγει λάθος σε μια αριθμητική συνάρτηση), και έστω ότι δεν έβγαινε λάθος τότε η ισχνή αναφορά θα έδειχνει αυτό που δεν θα υπήρχε (Αφού η συνάρτηση στην επιστροφή σβήνει ότι φτιάχνει, εκτός από την τιμή που γυρνάει). Ως όρισμα με αναφορά, επειδή η Διάβασε ενώνει την τοπική με αυτή που δίνουμε με αναφορά, κατά τη χρήση χρησιμοποιεί την εξωτερική, άρα αυτό που θα καταστρέψει στο τέλος εκτέλεσης της συνάρτησης είναι η ένωση, του ονόματος και όχι αυτό που αναφέρει η ένωση!
Από την 9η έκδοση οι ομάδες μπορούν να δίνουν δείκτη σε μεταβλητή και αυτή η μεταβλητή να χρησιμοποιείται ως να είναι η ομάδα. Η επώνυμη ομάδα πχ Αλφα δεν είναι δείκτης σε ομάδα (εσωτερικά όντως είναι δείκτης). Έτσι όταν ορίσουμε μια νέα μεταβλητή έστω Βήτα με το Βήτα=Αλφα τότε παράγεται αντίγραφο στο Βήτα. Με το Μ->Αλφα θα πάρουμε δείκτη της Αλφα και το Ζ=Μ θα κάνει αντιγραφή του δείκτη. Δείτε όμως ότι όπως υπάρχουν δυο τύποι ομάδων, οι επώνυμες και οι πτητικές ή ανώνυμες, έτσι και οι δείκτες εσωτερικά είναι δυο ειδών αλλά είναι αθέατοι στο χρήστη. Όμως υπάρχουν συνέπειες στην χρήση τους. Πχ το Μ παραπάνω δείχνει το Α ως αναφορά στο Α,και αν το Α χαθεί τότε το Μ μένει με ένα δείκτη που δεν δείχνει κάτι! Ουσιαστικά ο δείκτης αυτός είναι ισχνή αναφορά, οπότε γίνεται έλεγχος πριν την χρήση του. Αν δώσουμε Μ->(Αλφα) τότε το (Αλφα) θα είναι αντίγραφο της Άλφα ως ανώνυμη ομάδα (πτητική, γιατί μπορεί να μετακινηθεί), και το Μ έχει γνήσιο δείκτη. Εδώ η ζωή της ομάδας εξαρτιέται από τον αριθμό των δεικτών προς αυτήν. Όταν ο τελευταίος δείκτης διαγραφεί τότε θα πάρει εντολή το σύστημα να διαγράψει την ομάδα. Με αυτό το σύστημα μπορούμε να έχουμε δείκτες σε ομάδες που είναι σε πίνακες (ενώ δεν μπορούμε να έχουμε αναφορά σε στοιχεία πίνακα, μπορούμε να έχουμε γνήσιους δείκτες). Έτσι αν έχουμε ένα πίνακα Α() και δώσουμε αυτό Α(3)=Αλφα, θα μπει ένα αντίγραφο του Αλφα στο Α(3), και μετά αυτό Μ->Α(3) θα έχουμε ένα δείκτη Μ να δείχνει σε αυτό το αντίγραφο. Αν δώσουμε ξανά το Α(3)=Άλφα τότε το Μ θα δείχνει τη παλιά τιμή του Α(3).
Σε αντικείμενα σε άλλες γλώσσες ξεχωρίζει ο κώδικας (λέγεται Interface) από τα δεδομένα (λέγονται instance). Μάλιστα μπορούν να υπάρχουν πολλαπλά Interface για την ίδια παρουσία (instance).
Στη Μ2000 η ομάδα φέρει τον κώδικα και δεδομένα μαζί και δεν υπάρχει τύπος ή interface εκτός από το βασικό αυτό της Ομάδας.Το τμήμα Βήτα2 θα μπορούσε να πάρει οποιοδήποτε ομάδα. Βέβαια αφού χρησιμοποιούμε συγκεκριμένα ονόματα που σχετίζονται με την ομάδα σημαίνει ότι υλοποιούμε την χρήση ενός interface, ενός προσαρμογέα δηλαδή που συνομιλεί με το αντικείμενο. Απλά ορισμένες γλώσσες κάνουν έλεγχο τύπου πριν βγάλουν εκτελέσιμο κώδικα, ενώ στη Μ2000 μπορούμε να εφαρμόσουμε όποια στρατηγική θέλουμε στο πώς θα χειριστούμε την οποιαδήποτε ομάδα περάσουμε στο Βήτα2. Στις νεότερες εκδόσεις της γλώσσας μπορούμε να ορίσουμε τύπο ομάδας ώστε όταν ζητάμε τιμή γιαπαράμετρο σε μια συνάρτηση ή ένα τμήμα να ορίζουμε το όνομα του τύπου. Μια ομάδα μπορεί να έχει περισσότερους από ένα τύπο:
Ομάδα Αλφα1 {
Τύπος: Τύπος1
Χ=10, Ψ=20
}
Ζήτα=Αλφα1
Τύπωσε Ζήτα είναι τύπος Τύπος1 = Αληθές
Ομάδα Βήτα1 {
Τύπος: Τύπος2
Συνάρτηση Τετράγωνο (Χ) {
=Χ**2
}
}
Δέλτα=Αλφα1 με Βήτα1
Τύπωσε Δέλτα είναι τύπος Τύπος1 = Αληθές
Τύπωσε Δέλτα είναι τύπος Τύπος2 = Αληθές
Τύπωσε Δέλτα.Τετράγωνο(10)=100, Δέλτα.Ψ=20
Τύπωσε Δέλτα είναι Βήτα1=Ψευδές
Τύπος: Τύπος1
Χ=10, Ψ=20
}
Ζήτα=Αλφα1
Τύπωσε Ζήτα είναι τύπος Τύπος1 = Αληθές
Ομάδα Βήτα1 {
Τύπος: Τύπος2
Συνάρτηση Τετράγωνο (Χ) {
=Χ**2
}
}
Δέλτα=Αλφα1 με Βήτα1
Τύπωσε Δέλτα είναι τύπος Τύπος1 = Αληθές
Τύπωσε Δέλτα είναι τύπος Τύπος2 = Αληθές
Τύπωσε Δέλτα.Τετράγωνο(10)=100, Δέλτα.Ψ=20
Τύπωσε Δέλτα είναι Βήτα1=Ψευδές
Εδώ καλό είναι να αναφερθεί ότι σε πίνακες που δηλώνονται ότι θα γεμίσουν με συγκεκριμένη ομάδα, οι συναρτήσεις/τμήματα/τελεστές πάνε σε ένα σημείο ως κοινός κώδικας. Αυτό περιορίζει την συνεχή αντιγραφή του κώδικα για κάθε στοιχείο του πίνακα (γίνεται για οικονομία αλλά έχει άλλο νόημα, ο πίνακας είναι ένα σύνολο, μια διατεταγμένη σειρά ομάδων, ενός τύπου ομάδας). Μπορούμε όμως να έχουμε πίνακα με διαφορετικές ομάδες, άρα σε κάθε μια θα υπάρχει όλο το σετ, και ο κώδικας και τα δεδομένα. (Οι υπολογιστές έχουν τεράστια μνήμη σε σχέση με το μέγεθος του κώδικα ενός αντικειμένου).
Επίσης οι ομάδες μπορούν να έχουν και άλλες ομάδες εσωτερικά (τέτοιες είναι και οι ιδιότητες, είναι ομάδες σε ομάδες). Τα μέλη μιας ομάδας μπορεί να είναι μεταβλητές, πίνακες, γεγονότα, λάμδα συναρτήσεις, συναρτήσεις, τμήματα, καταστάσεις, διαρθρώσεις, σωροί και άλλες ομάδες. Με απλά λόγια μια ομάδα μπορεί να έχει τα πάντα!
Έχει σημασία για τη Μ2000 η έννοια Ανοικτό και Κλειστό αντικείμενο. Το κλειστό δεν έχει όνομα, και ό,τι έχει είναι απομονωμένο σε ιδιωτική λίστα. Με κανένα τρόπο δεν μπορεί "τυχαία" να δούμε κάτι σε ένα κλειστό αντικείμενο. Κάθε φορά που θέλουμε να αλλάξουμε ή να διαβάσουμε κάτι από μια ομάδα πρέπει να είναι ανοικτή, δηλαδή τα μέλη της να είναι θεατά, να είναι στο σύστημα ονομάτων της Μ2000 (χώρος ονομάτων, namespace). Κλειστές ομάδες (λέγονται και πτητικές), είναι αυτές που βρίσκονται οπουδήποτε δεν υπάρχει όνομα αλλά μόνο θέση. Έτσι σε ένα πίνακα υπάρχουν θέσεις, σε μια Κατάσταση το ίδιο (λίστα με κλειδιά), στο σωρό το ίδιο, και ως επιστρεφόμενη τιμή έχει θέση στην επιστροφή, δηλαδή σε όλες αυτές τις περιπτώσεις έχουμε κλειστό αντικείμενο.
Η έννοια του κλειστού αντικειμένου σε άλλες γλώσσες δεν υπάρχει, γιατί εκεί ένα αντικείμενο δένεται με ένα δείκτη, και η πρόσβαση είναι πάντα μέσω αυτού. Στη Μ2000 τα μέλη μιας ομαδας λειτουργούν ανεξάρτητα από την ομάδα, δηλαδή καλούνται απ΄ευθείας, ως ξεχωριστές παρουσίες, και απλά γνωρίζουν ότι αποτελούν μέλος ομάδας όπως και η ομάδα ξέρει ποια έχει μέλη, έχοντας λίστα με αναφορές σε αυτά. Στα αντικείμενα με δείκτες δεν έχουμε αναφορές σε μέλη αλλά έχουμε offset, δηλαδή αυτό που προσθέτουμε στη βάση (θέση μνήμης) των δεδομένων (αυτό που λέμε παρουσία) και αποτελεί τη θέση των δεδομένων του μέλους. Οι ομάδες όπως έχει αναφερθεί παραπάνω από την έκδοση 9 μπορούν να έχουν δείκτες, και μπορούμε να έχουμε μέλη ομάδας δείκτες σε ομάδες (εκτός από ομάδες).
Ένα προχωρημένο παράδειγμα, με χρήση μιας κλάσης, μιας συνάρτησης που παράγει μια "πτητική" ομάδα, εδώ με ένα μέλος καθώς και έναν κατασκευαστή με το όνομα της κλάσης (το οποίο φτιάχνεται προσωρινά στη κλάση, και για το λόγο αυτό βρίσκεται μετά την ετικέτα Κλάση).
Αναβάθμισα το παράδειγμα. Δείχνω πως καλείται η Διαγραφή αυτόματα για τις μη επώνυμες, και πως για τις επώνυμες ομάδες. Τα α, κ, κ1 είναι δείκτες σε ομάδα, το ζ είναι επώνυμη ομάδα.
Αντί για κ->α μπορούμε να βάλουμε το κ=Δείκτης(α). Για τις επώνυμες το κ=Δείκτης(ζ) με το κ=Δείκτης((ζ)) διαφέρει, το τελευταίο είναι δείκτης σε αντίγραφο. Με την κ->(ομάδα(κ1)) φτιάχνουμε μια νέα ομάδα με το ομάδα(κ1) από το δείκτη κ1 και δίνουμε το δείκτη στο κ, έτσι θα δούμε δυο φορές το Διαγραφή 100, ένα για το κ και ένα για το κ1. Το κ->0& και το κ=Δείκτης() είναι ισοδύναμα, δίνουμε την ομάδα με τύπο Μηδενικός (Null). Η δείκτης μας βολεύει όπου δεν μπορούμε να βάλουμε το ->. Οι συναρτήσεις εκτός από το = για επιστροφή τιμής έχουν και το -> για επιστροφή δείκτη (πάντα σε ομάδες).
Τμήμα βήτα {
Κλάση Άλφα {
Ένας_Αριθμός
Μ=100
Διαγραφή {
Τύπωσε "Διαγραφή", .Μ
}
Κλάση:
Τμήμα Άλφα (.Ένας_Αριθμός){}
}
α->Αλφα(12345)
Λίστα
κ->α
κ1=κ
Τυπωσε κ=>Ένας_Αριθμός=12345
κ->0& ' ένας τρόπος διαγραφής δείκτη
Τύπωσε Τύπος$(κ)="Group" ' ο τύπος παραμένει όμως
Τύπωσε κ είναι τύπος Άλφα=Αληθής // Στις νέες εκδόσεις, οι κλάσεις έχουν τύπο το όνομά τους!
Τυπωσε κ1=>Ένας_Αριθμός=12345
// Καθαρό α // η Καθαρό α, χαλάει την α, ενώ η Δείκτης() της δίνει μηδενικό τύπο (Null)
// με δείκτη Null μπορεί να χρησιμοποιηθεί ξανά, να δώσουμε άλλο δείκτη.
// ενώ η Καθαρό α, την βγάζει εκτός, την κάνει άχρηστη
α=Δείκτης()
Τύπωσε Τύπος$(α)="Group"
Τύπωσε α είναι τύπος μηδενικός=Αληθές
Τύπωσε Έγκυρο(α=>Ένας_Αριθμός)=Ψευδές ' δεν υπάρχει
ζ=Ομάδα(κ1)
ζ.Μ+=100
Καθαρό ζ ' τώρα καλεί την διαγραφή, βλέπουμε το Διαγραφή
// θα δούμε το Διαγραφή 200 (θα καθαρίσει η ζ, που είναι επώνυμη)
// μόλις τερματίσει το τμήμα θα διαγραφεί το κ1, και θα κληθεί η Διαγραφή σε αυτό αυτόματα
// έτσι θα δούμε το Διαγραφή 100
κ->(ομάδα(κ1))
}
βήτα
Αν σε μια παράμετρο θέλουμε να έχουμε δείκτη σε ομάδα τότε γράφουμε Διάβασε α ως δείκτης, ενώ αν θέλουμε συγκεκριμένου τύπου (μπορεί η ομάδα να έχει και άλλους τύπους), τότε γράφουμε Διάβασε α ως *ΌνομαΤύπου. Στους ορισμούς αντί της Διάβασε, αν θέλουμε, γράφουμε σε παρενθέσεις (α ως *Αλφα) αλλά ο διερμηνευτής θα φτιάξει μη Διάβασε απλά με αντιγραφή ότι βάλουμε ανάμεσα στις παρενθέσεις). Οι παρενθέσεις εδώ έχουν την θέση της συνακτικής ζάχαρης (syntactic sugar) όπως λέγεται!
Στις επώνυμες ομάδες η Μ2000 μπορεί να περάσει με αναφορά ένα μέλος της, γιατί το μέλος της έχει την δική του παρουσία, όπως επίσης μπορεί να προσθέσει μέλη, γιατί δεν έχει ανάγκη να βρίσκονται αυτά σε συνεχόμενη μνήμη. Το ζήτημα είναι με την αναφορά της ομάδας, επειδή πρέπει να φτιαχτούν τόσες αναφορές όσες και τα μέλη μιας ομάδας, αν περάσουμε ομάδα με αναφορά! Μπορούμε όμως να το ξεπεράσουμε με την χρήση της ισχνής αναφοράς, που την διατηρούμε συνέχεια. Εδώ στην Βήτα3 κρατάμε την ισχνή αναφορά που παράγει το &Αλφα σε ένα αλφαριθμητικό. Η Εκφρ$() επιλύει την αναφορά κατά τη χρήση (σε δεξιές εκφράσεις χρησιμοποιούμε την Εκφρ$() ή την Εκφρ$(), ενώ στις αριστερές όπως στην κλήση του ΚάνεΚάτι το βλέπει άμεσα ο διερμηνευτής, και αλλάζει το ΜιαΟμάδα$. με αυτό που δείχνει το ΜιαΟμάδα$ (βάλτε μια Τύπωσε ΜιαΟμαδα$ να δείτε τι έχει!). Όπως αναφέρθηκε παραπάνω μπορούμε να περάσουμε ένα δείκτη μιας επώνυμης ομάδας ακόμα και χωρίς αναφορά, και θα πάρουμε έναν νέο δείκτη που πάλι θα είναι αναφορά στην ομάδα. Έτσι εδώ δεν χρησιμοποιούμε το αλφαριθμητικό, αλλά το όνομα του δείκτη και το παχύ βέλος => για τα μέλη, χωρίς την χρήση της Έκφρ$() ή της Εκφρ().
Με αυτόν τον τρόπο δεν παράγουμε αναφορά για κάθε μέλος, ούτε καν για την ομάδα, αλλά χρησιμοποιούμε το αλφαριθμητικό ως δείκτη. Αυτός είναι ένας τρόπος να χρησιμοποιεί δείκτες ως ισχνές αναφορές στη Μ2000. (δεν είναι διευθύνσεις στη μνήμη αλλά είναι πρόθεμα ή ολόκληρο όνομα μιας μεταβλητής που βρίσκει άμεσα ο διερμηνευτής, βάσει ενός πίνακα κατακερματισμού)
'Ενα "ανοικτό" αντικείμενο Ομάδα έχει τα μέλη σε αυτόν τον πίνακα κατακερματισμού. Ενώ ένα κλειστό όχι. Στο 2.6 γίνεται περισσότερος λόγος για τις ανώνυμες, ή πτητικές ομάδες, τα κλειστά αντικείμενα δηλαδή.
Η ονομασία ισχνή αναφορά βγαίνει από το γεγονός ότι η αναφορά μπορεί να γίνει φυσική αναφορά για το χρόνο της ζήτησης και εφόσον πράγματι υπάρχει αυτό που αναφέρει. Στο τμήμα Βήτα2 η κλήση δίνει ισχνή αναφορά αλλά η Διάβασε την κάνει φυσική αναφορά φτιάχνοντας όλα τα μέλη με άλλο όνομα ομάδας ως αναφορές. Κατά τη χρήση δεν γίνεται καμία "επίλυση" αναφοράς, ήδη λειτουργεί η αναφορά, αφού το όνομα δείχνει απ΄ευθείας στο αναφερόμενο μέλος! Αν δηλαδή έχουμε πολύ δουλειά να κάνουμε με μέλη μιας ομάδας με αναφορά, είναι προτιμότερο να περαστεί ως κανονική αναφορά.
Δείτε και ο Βήτα4 με πέρασμα με δείκτη
Βήτα3 &Άλφα
2.4.1 Χρήση = και <= για τις μεταβλητές ομάδων
Έχει σημασία στην Μ2000 η χρήση των = και <= κατά την εκχώρηση τιμής. Η χρήση του <= γίνεται όταν θέλουμε να αποφύγει ο διερμηνευτής να κάνει τοπική μια μεταβλητή. Λέγοντας τοπική σημαίνει να προσθέσει στο όνομά της (χωρίς να φαίνεται στο κώδικα) το όνομα χώρου, δηλαδή το όνομα του τμήματος ή της συνάρτησης που ανήκει.
Όταν φτιάχνουμε ομάδες με την εντολή ομάδα τότε οι μεταβλητές κατά τη δημιουργία στον ορισμό ομάδας θέλουν το "=" ενώ για εκχώρηση τιμής θέλουν το "<=" μέσα σε τμήματα και συναρτήσεις που περιέχονται σε ομάδες.
Εδώ στο παράδειγμα δείχνει τα ονόματα μεταβλητών και τι γίνεται με την περίπτωση που έχουμε μια ομάδα που έγινε από άλλη ομάδα εντός ενός τμήματος εντός μιας ομάδας!
Στα παραδείγματα έχει γίνει αναπρογραμματισμός της εντολής Λίστα με ένα γενικό τμήμα Λίστα
Όταν γυρνάμε στη γραμμή εντολών η Λίστα είναι η κανονική. Εντός του γενικού τμήματος λίστα καλούμε την κανονική εντολή με το @ στην αρχή.
Στα προγράμματα παρακάτω η εντολή Λίστα εμφανίζει τα ονόματα των μεταβλητών με τα προθέματά τους ανάλογα με ποιον τύπο διερμηνευτή χρησιμοποιούμε. Εξ ορισμού σε χρήση είναι ο "Secure", που παρέχει τη μέγιστη ασφάλεια. Μπορούμε να δοκιμάσουμε και τους δύο. Δίνουμε από τη γραμμή εντολών της Μ2000 το Διακόπτες "-sec" για τον παλιό, και το Διακόπτες "+sec" για τον νέο. Βλέπουμε την κατάσταση και με την εντολή 'Ελεγχος ή Monitor (δίνει στα αγγλικά μερικά μηνύματα, σε επόμενη αναθεώρηση θα φτιαχτεί να δίνει ελληνικά όταν εκτελούμε την εντολή στα ελληνικά).
' Έστω ο κώδικας ανήκει στο τμήμα Α
Φόρμα 60,30
Τμήμα Γενικό Λίστα {
Αναφορά 2, "Λίστα Μεταβλητών "
@Λίστα !
Αναφορά 2, "Πάτα ένα πλήκτρο"
α$=Κομ$
}
Τμήμα Μεγάλο {
' Φτιάχνουμε το τμήμα Ένα σε μια ομάδα Πρώτη
Ομάδα Πρώτη {
Τμήμα Ένα {
Οθόνη ,0
Διπλά
Αναφορά 2, "Τμήμα "+Τμήμα$
Κανονικά
Οθόνη ,2
Ομάδα άλφα {
χ=10, ψ=3
}
Αναφορά μορφη$("Τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}", άλφα.χ, άλφα.ψ)
Λιστα
' Το παρακάτω τυπώνει τιμή με χρήση δείκτη (σε αλφαριθμητικό),
' εδώ η Τμήμα$ έχει το τρέχον όνομα του τμήματος
Αναφορά Μορφή$("{0}.Αλφα.χ = {1}", Τμήμα$, Εκφρ(Τμήμα$.Άλφα.Χ))
Για Άλφα {
' Εδώ το = δεν έχει θέμα γιατί η Άλφα έχει φτιαχτεί με ορισμό Ομάδα εντός τμήματος
' Το τμήμα όμως είναι τμήμα Ομάδας
.χ=20
.ψ+=10
Λίστα
Αναφορά Μορφή$("Νέες τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}",.χ, .ψ)
}
' το "μυστήριο" ξεκινάει εδώ, όπου το Ζήτα δημιουργείται από το Άλφα
' τα Ζήτα.χ και Ζήτα.ψ δεν έχουν πρόθεμα εσωτερικά το Τμήμα$
Ζήτα = Άλφα
Λίστα
Για Ζήτα {
Αναφορά Μορφή$("Ζήτα.χ και Ζήτα.ψ = {0}, {1}", .χ, .ψ)
}
' Όπότε η αλλαγή τιμής κανονικά γίνεται με <= σαν να είναι γενική
Ζήτα.χ<=300
Δες οκ {
Αναφορά "Δοκιμή της Εκφρ(Τμήμα$.Ζήτα.χ)"
Αναφορά Μορφή$("{0}.Ζήτα.χ={1}", Τμήμα$, Εκφρ(Τμήμα$.Ζήτα.χ))
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
Τμήμα Κάπα {
' Πράγματι εδώ στο Κάπα η Ζήτα.χ φαίνεται!
Αναφορά Μορφή$("Εντός Κάπα το Ζήτα.χ = {0} ", Ζήτα.χ)
' δίνει Όχι γιατί το Ζήτα δεν είναι γενικό!
Αναφορά Μορφή$("Έίναι έγκυρο το Ζήτα: {0}", Γραφή$(Έγκυρο(Ζήτα),{"Ναι";"Ναι";"Όχι"}) )
}
Κάπα
' αν κάνουμε λάθος και βάλουμε το Ζήτα.χ με =
Ζήτα.χ=1000
' Το λάθος δεν θα φανεί γιατί θα δημιουργηθεί τοπική Ζήτα.χ
Αναφορά Μορφή$("ΜεΖήτα.χ=1000 φτιάξαμε τοπική με τιμή: {0}" , Ζήτα.χ)
Λίστα
Κάπα ' εδώ η κάπα τυπώνει το 300
Δέλτα=Ζήτα
Αναφορά Μορφή$("Η Δέλτα.χ πήρε τη κανονική τιμή: {0}" , Δέλτα.χ)
Λίστα
}
}
' Τώρα το καλούμε
Πρώτη.Ένα
' Τώρα το καλούμε με την κάλεσε
Κάλεσε Πρώτη.Ένα
}
Μεγάλο
Κάλεσε Μεγάλο
Και εδώ είναι ο κώδικας για την περίπτωση που δημιουργούμε ομάδα εντός τμήματος που δεν ανήκει σε ομάδα:
' Έστω ο κώδικας ανήκει στο τμήμα Α
Φόρμα 60,30
Τμήμα Γενικό Λίστα {
Αναφορά 2, "Λίστα Μεταβλητών "
@Λίστα !
Αναφορά 2, "Πάτα ένα πλήκτρο"
α$=Κομ$
}
Τμήμα Μεγάλο {
Τμήμα Ένα {
Οθόνη ,0
Διπλά
Αναφορά 2, "Τμήμα "+Τμήμα$
Κανονικά
Οθόνη ,2
Ομάδα άλφα {
χ=10, ψ=3
}
Αναφορά μορφη$("Τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}", άλφα.χ, άλφα.ψ)
Λιστα
' στην απλή κλήση
' Βλέπουμε ότι υπάρχουν οι μεταβλητές
' ΕΝΑ.ΑΛΦΑ[Group], ΕΝΑ.ΑΛΦΑ.Χ=10, ΕΝΑ.ΑΛΦΑ.Ψ=3
' στη κλήση με την κάλεσε αλλάζουν τα ονόματα
' ΜΕΓΑΛΟ[1].ΑΛΦΑ[Group], ΜΕΓΑΛΟ[1].ΑΛΦΑ.Χ=10, ΜΕΓΑΛΟ[1].ΑΛΦΑ.Ψ=3
' ή αν έχει γίνει η Κάλεσε Μεγάλο και μετά η Κάλεσε Ένα
' Α[2].ΑΛΦΑ[Group], Α[2].ΑΛΦΑ.Χ=10, Α[2].ΑΛΦΑ.Ψ=3
' Το παρακάτω τυπώνει τιμή με χρήση δείκτη (σε αλφαριθμητικό),
' εδώ η Τμήμα$ έχει το τρέχον όνομα του τμήματος
Αναφορά Μορφή$("{0}.Αλφα.χ = {1}", Τμήμα$, Εκφρ(Τμήμα$.Άλφα.Χ))
Για Άλφα {
' Εδώ το = δεν έχει θέμα γιατί η Άλφα έχει φτιαχτεί με ορισμό Ομάδα εντός τμήματος
' Το τμήμα όμως είναι τμήμα Ομάδας
.χ=20
.ψ+=10
Λίστα
Αναφορά Μορφή$("Νέες τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}",.χ, .ψ)
}
' το "μυστήριο" ξεκινάει εδώ, όπου το Ζήτα δημιουργείται από το Άλφα
' τα Ζήτα.χ και Ζήτα.ψ δεν έχουν πρόθεμα εσωτερικά το Τμήμα$
Ζήτα = Άλφα
Λίστα
Για Ζήτα {
Αναφορά Μορφή$("Ζήτα.χ και Ζήτα.ψ = {0}, {1}", .χ, .ψ)
}
' Όπότε η αλλαγή τιμής κανονικά γίνεται με <= σαν να είναι γενική
Δες οκ {
Αναφορά "Δοκιμή της Ζήτα.χ<=300"
Ζήτα.χ<=300
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
Δες οκ {
Αναφορά "Δοκιμή της Εκφρ(Τμήμα$.Ζήτα.χ)"
Αναφορά Μορφή$("{0}.Ζήτα.χ={1}", Τμήμα$, Εκφρ(Τμήμα$.Ζήτα.χ))
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
Τμήμα Κάπα {
Δες οκ {
Αναφορά "Δοκιμή της Ζήτα.χ εντός της Κάπα"
Αναφορά Μορφή$("Εντός Κάπα το Ζήτα.χ = {0} ", Ζήτα.χ)
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
' δίνει Όχι γιατί το Ζήτα δεν είναι γενικό!
Αναφορά Μορφή$("Έίναι έγκυρο το Ζήτα: {0}", Γραφή$(Έγκυρο(Ζήτα),{"Ναι";"Ναι";"Όχι"}) )
}
Κάπα
Ζήτα.χ=1000
Αναφορά Μορφή$("ΜεΖήτα.χ=1000 δώσαμε τιμή: {0}" , Ζήτα.χ)
Λίστα
Δέλτα=Ζήτα
Αναφορά Μορφή$("Η Δέλτα.χ έχει τη κανονική τιμή: {0}" , Δέλτα.χ)
Λίστα
}
' Τώρα καλούμε
Ένα
' Τώρα το καλούμε με την κάλεσε
Κάλεσε Ένα
}
Μεγάλο
Κάλεσε Μεγάλο
2.5. Ορισμός Κλάσης
Κλάση Αλφα1 {
Β=10, Α
Τμήμα ΚάνεΚάτι {
Τύπωσε .Α*2+.Β
.Β+=.Α*2
}
}
Άλφα=Αλφα1()
Για Άλφα {
Σωρός Νέος {
Σειρά 20, 30, 40
Ενώ όχι κενό {
Διάβασε .Α
.ΚάνεΚάτι
}
}
}
Βήτα=Αλφα1()
Για Βήτα {
Σωρός Νέος {
Σειρά 25, 45, 85
Ενώ όχι κενό {
Διάβασε .Α
.ΚάνεΚάτι
}
}
}
Τμήμα βήτα {
Κλάση Άλφα {
Ένας_Αριθμός
Μ=100
Διαγραφή {
Τύπωσε "Διαγραφή", .Μ
}
Κλάση:
Τμήμα Άλφα (.Ένας_Αριθμός){}
}
α->Αλφα(12345)
Λίστα
κ->α
κ1=κ
Τυπωσε κ=>Ένας_Αριθμός=12345
κ->0& ' ένας τρόπος διαγραφής δείκτη
Τύπωσε Τύπος$(κ)="Group" ' ο τύπος παραμένει όμως
Τύπωσε κ είναι τύπος Άλφα=Αληθής // Στις νέες εκδόσεις, οι κλάσεις έχουν τύπο το όνομά τους!
Τυπωσε κ1=>Ένας_Αριθμός=12345
// Καθαρό α // η Καθαρό α, χαλάει την α, ενώ η Δείκτης() της δίνει μηδενικό τύπο (Null)
// με δείκτη Null μπορεί να χρησιμοποιηθεί ξανά, να δώσουμε άλλο δείκτη.
// ενώ η Καθαρό α, την βγάζει εκτός, την κάνει άχρηστη
α=Δείκτης()
Τύπωσε Τύπος$(α)="Group"
Τύπωσε α είναι τύπος μηδενικός=Αληθές
Τύπωσε Έγκυρο(α=>Ένας_Αριθμός)=Ψευδές ' δεν υπάρχει
ζ=Ομάδα(κ1)
ζ.Μ+=100
Καθαρό ζ ' τώρα καλεί την διαγραφή, βλέπουμε το Διαγραφή
// θα δούμε το Διαγραφή 200 (θα καθαρίσει η ζ, που είναι επώνυμη)
// μόλις τερματίσει το τμήμα θα διαγραφεί το κ1, και θα κληθεί η Διαγραφή σε αυτό αυτόματα
// έτσι θα δούμε το Διαγραφή 100
κ->(ομάδα(κ1))
}
βήτα
Στις επώνυμες ομάδες η Μ2000 μπορεί να περάσει με αναφορά ένα μέλος της, γιατί το μέλος της έχει την δική του παρουσία, όπως επίσης μπορεί να προσθέσει μέλη, γιατί δεν έχει ανάγκη να βρίσκονται αυτά σε συνεχόμενη μνήμη. Το ζήτημα είναι με την αναφορά της ομάδας, επειδή πρέπει να φτιαχτούν τόσες αναφορές όσες και τα μέλη μιας ομάδας, αν περάσουμε ομάδα με αναφορά! Μπορούμε όμως να το ξεπεράσουμε με την χρήση της ισχνής αναφοράς, που την διατηρούμε συνέχεια. Εδώ στην Βήτα3 κρατάμε την ισχνή αναφορά που παράγει το &Αλφα σε ένα αλφαριθμητικό. Η Εκφρ$() επιλύει την αναφορά κατά τη χρήση (σε δεξιές εκφράσεις χρησιμοποιούμε την Εκφρ$() ή την Εκφρ$(), ενώ στις αριστερές όπως στην κλήση του ΚάνεΚάτι το βλέπει άμεσα ο διερμηνευτής, και αλλάζει το ΜιαΟμάδα$. με αυτό που δείχνει το ΜιαΟμάδα$ (βάλτε μια Τύπωσε ΜιαΟμαδα$ να δείτε τι έχει!). Όπως αναφέρθηκε παραπάνω μπορούμε να περάσουμε ένα δείκτη μιας επώνυμης ομάδας ακόμα και χωρίς αναφορά, και θα πάρουμε έναν νέο δείκτη που πάλι θα είναι αναφορά στην ομάδα. Έτσι εδώ δεν χρησιμοποιούμε το αλφαριθμητικό, αλλά το όνομα του δείκτη και το παχύ βέλος => για τα μέλη, χωρίς την χρήση της Έκφρ$() ή της Εκφρ().
Με αυτόν τον τρόπο δεν παράγουμε αναφορά για κάθε μέλος, ούτε καν για την ομάδα, αλλά χρησιμοποιούμε το αλφαριθμητικό ως δείκτη. Αυτός είναι ένας τρόπος να χρησιμοποιεί δείκτες ως ισχνές αναφορές στη Μ2000. (δεν είναι διευθύνσεις στη μνήμη αλλά είναι πρόθεμα ή ολόκληρο όνομα μιας μεταβλητής που βρίσκει άμεσα ο διερμηνευτής, βάσει ενός πίνακα κατακερματισμού)
'Ενα "ανοικτό" αντικείμενο Ομάδα έχει τα μέλη σε αυτόν τον πίνακα κατακερματισμού. Ενώ ένα κλειστό όχι. Στο 2.6 γίνεται περισσότερος λόγος για τις ανώνυμες, ή πτητικές ομάδες, τα κλειστά αντικείμενα δηλαδή.
Η ονομασία ισχνή αναφορά βγαίνει από το γεγονός ότι η αναφορά μπορεί να γίνει φυσική αναφορά για το χρόνο της ζήτησης και εφόσον πράγματι υπάρχει αυτό που αναφέρει. Στο τμήμα Βήτα2 η κλήση δίνει ισχνή αναφορά αλλά η Διάβασε την κάνει φυσική αναφορά φτιάχνοντας όλα τα μέλη με άλλο όνομα ομάδας ως αναφορές. Κατά τη χρήση δεν γίνεται καμία "επίλυση" αναφοράς, ήδη λειτουργεί η αναφορά, αφού το όνομα δείχνει απ΄ευθείας στο αναφερόμενο μέλος! Αν δηλαδή έχουμε πολύ δουλειά να κάνουμε με μέλη μιας ομάδας με αναφορά, είναι προτιμότερο να περαστεί ως κανονική αναφορά.
Δείτε και ο Βήτα4 με πέρασμα με δείκτη
Τμήμα
Βήτα3 {
Διάβασε ΜιαΟμάδα$ \\ διαβάζει την ομάδα ως ισχνή αναφορά
Τύπωσε Εκφρ(ΜιαΟμάδα$.) \\ 106 - δείτε την τελεία μετά το $
\\ όμως εδώ έχουμε την ομάδα
ΜιαΟμάδα$.ΚάνεΚάτι \\ 130 - δείτε την τελεία μετά το $
Τύπωσε Εκφρ(ΜιαΟμάδα$.) \\ 130 }
Διάβασε ΜιαΟμάδα$ \\ διαβάζει την ομάδα ως ισχνή αναφορά
Τύπωσε Εκφρ(ΜιαΟμάδα$.) \\ 106 - δείτε την τελεία μετά το $
\\ όμως εδώ έχουμε την ομάδα
ΜιαΟμάδα$.ΚάνεΚάτι \\ 130 - δείτε την τελεία μετά το $
Τύπωσε Εκφρ(ΜιαΟμάδα$.) \\ 130 }
Βήτα3 &Άλφα
μ->Άλφα
Τμήμα
Βήτα4 {
Διάβασε μ
Τύπωσε Εκφρ(μ) ' 130
μ=>ΚάνεΚάτι ' 154
Τύπωσε Εκφρ(μ) ' 154 } Βήτα4 μ Τύπωσε Άλφα=154 ' Αληθές
Διάβασε μ
Τύπωσε Εκφρ(μ) ' 130
μ=>ΚάνεΚάτι ' 154
Τύπωσε Εκφρ(μ) ' 154 } Βήτα4 μ Τύπωσε Άλφα=154 ' Αληθές
2.4.1 Χρήση = και <= για τις μεταβλητές ομάδων
Έχει σημασία στην Μ2000 η χρήση των = και <= κατά την εκχώρηση τιμής. Η χρήση του <= γίνεται όταν θέλουμε να αποφύγει ο διερμηνευτής να κάνει τοπική μια μεταβλητή. Λέγοντας τοπική σημαίνει να προσθέσει στο όνομά της (χωρίς να φαίνεται στο κώδικα) το όνομα χώρου, δηλαδή το όνομα του τμήματος ή της συνάρτησης που ανήκει.
Όταν φτιάχνουμε ομάδες με την εντολή ομάδα τότε οι μεταβλητές κατά τη δημιουργία στον ορισμό ομάδας θέλουν το "=" ενώ για εκχώρηση τιμής θέλουν το "<=" μέσα σε τμήματα και συναρτήσεις που περιέχονται σε ομάδες.
Εδώ στο παράδειγμα δείχνει τα ονόματα μεταβλητών και τι γίνεται με την περίπτωση που έχουμε μια ομάδα που έγινε από άλλη ομάδα εντός ενός τμήματος εντός μιας ομάδας!
Στα παραδείγματα έχει γίνει αναπρογραμματισμός της εντολής Λίστα με ένα γενικό τμήμα Λίστα
Όταν γυρνάμε στη γραμμή εντολών η Λίστα είναι η κανονική. Εντός του γενικού τμήματος λίστα καλούμε την κανονική εντολή με το @ στην αρχή.
Στα προγράμματα παρακάτω η εντολή Λίστα εμφανίζει τα ονόματα των μεταβλητών με τα προθέματά τους ανάλογα με ποιον τύπο διερμηνευτή χρησιμοποιούμε. Εξ ορισμού σε χρήση είναι ο "Secure", που παρέχει τη μέγιστη ασφάλεια. Μπορούμε να δοκιμάσουμε και τους δύο. Δίνουμε από τη γραμμή εντολών της Μ2000 το Διακόπτες "-sec" για τον παλιό, και το Διακόπτες "+sec" για τον νέο. Βλέπουμε την κατάσταση και με την εντολή 'Ελεγχος ή Monitor (δίνει στα αγγλικά μερικά μηνύματα, σε επόμενη αναθεώρηση θα φτιαχτεί να δίνει ελληνικά όταν εκτελούμε την εντολή στα ελληνικά).
' Έστω ο κώδικας ανήκει στο τμήμα Α
Φόρμα 60,30
Τμήμα Γενικό Λίστα {
Αναφορά 2, "Λίστα Μεταβλητών "
@Λίστα !
Αναφορά 2, "Πάτα ένα πλήκτρο"
α$=Κομ$
}
Τμήμα Μεγάλο {
' Φτιάχνουμε το τμήμα Ένα σε μια ομάδα Πρώτη
Ομάδα Πρώτη {
Τμήμα Ένα {
Οθόνη ,0
Διπλά
Αναφορά 2, "Τμήμα "+Τμήμα$
Κανονικά
Οθόνη ,2
Ομάδα άλφα {
χ=10, ψ=3
}
Αναφορά μορφη$("Τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}", άλφα.χ, άλφα.ψ)
Λιστα
' Το παρακάτω τυπώνει τιμή με χρήση δείκτη (σε αλφαριθμητικό),
' εδώ η Τμήμα$ έχει το τρέχον όνομα του τμήματος
Αναφορά Μορφή$("{0}.Αλφα.χ = {1}", Τμήμα$, Εκφρ(Τμήμα$.Άλφα.Χ))
Για Άλφα {
' Εδώ το = δεν έχει θέμα γιατί η Άλφα έχει φτιαχτεί με ορισμό Ομάδα εντός τμήματος
' Το τμήμα όμως είναι τμήμα Ομάδας
.χ=20
.ψ+=10
Λίστα
Αναφορά Μορφή$("Νέες τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}",.χ, .ψ)
}
' το "μυστήριο" ξεκινάει εδώ, όπου το Ζήτα δημιουργείται από το Άλφα
' τα Ζήτα.χ και Ζήτα.ψ δεν έχουν πρόθεμα εσωτερικά το Τμήμα$
Ζήτα = Άλφα
Λίστα
Για Ζήτα {
Αναφορά Μορφή$("Ζήτα.χ και Ζήτα.ψ = {0}, {1}", .χ, .ψ)
}
' Όπότε η αλλαγή τιμής κανονικά γίνεται με <= σαν να είναι γενική
Ζήτα.χ<=300
Δες οκ {
Αναφορά "Δοκιμή της Εκφρ(Τμήμα$.Ζήτα.χ)"
Αναφορά Μορφή$("{0}.Ζήτα.χ={1}", Τμήμα$, Εκφρ(Τμήμα$.Ζήτα.χ))
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
Τμήμα Κάπα {
' Πράγματι εδώ στο Κάπα η Ζήτα.χ φαίνεται!
Αναφορά Μορφή$("Εντός Κάπα το Ζήτα.χ = {0} ", Ζήτα.χ)
' δίνει Όχι γιατί το Ζήτα δεν είναι γενικό!
Αναφορά Μορφή$("Έίναι έγκυρο το Ζήτα: {0}", Γραφή$(Έγκυρο(Ζήτα),{"Ναι";"Ναι";"Όχι"}) )
}
Κάπα
' αν κάνουμε λάθος και βάλουμε το Ζήτα.χ με =
Ζήτα.χ=1000
' Το λάθος δεν θα φανεί γιατί θα δημιουργηθεί τοπική Ζήτα.χ
Αναφορά Μορφή$("ΜεΖήτα.χ=1000 φτιάξαμε τοπική με τιμή: {0}" , Ζήτα.χ)
Λίστα
Κάπα ' εδώ η κάπα τυπώνει το 300
Δέλτα=Ζήτα
Αναφορά Μορφή$("Η Δέλτα.χ πήρε τη κανονική τιμή: {0}" , Δέλτα.χ)
Λίστα
}
}
' Τώρα το καλούμε
Πρώτη.Ένα
' Τώρα το καλούμε με την κάλεσε
Κάλεσε Πρώτη.Ένα
}
Μεγάλο
Κάλεσε Μεγάλο
Και εδώ είναι ο κώδικας για την περίπτωση που δημιουργούμε ομάδα εντός τμήματος που δεν ανήκει σε ομάδα:
' Έστω ο κώδικας ανήκει στο τμήμα Α
Φόρμα 60,30
Τμήμα Γενικό Λίστα {
Αναφορά 2, "Λίστα Μεταβλητών "
@Λίστα !
Αναφορά 2, "Πάτα ένα πλήκτρο"
α$=Κομ$
}
Τμήμα Μεγάλο {
Τμήμα Ένα {
Οθόνη ,0
Διπλά
Αναφορά 2, "Τμήμα "+Τμήμα$
Κανονικά
Οθόνη ,2
Ομάδα άλφα {
χ=10, ψ=3
}
Αναφορά μορφη$("Τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}", άλφα.χ, άλφα.ψ)
Λιστα
' στην απλή κλήση
' Βλέπουμε ότι υπάρχουν οι μεταβλητές
' ΕΝΑ.ΑΛΦΑ[Group], ΕΝΑ.ΑΛΦΑ.Χ=10, ΕΝΑ.ΑΛΦΑ.Ψ=3
' στη κλήση με την κάλεσε αλλάζουν τα ονόματα
' ΜΕΓΑΛΟ[1].ΑΛΦΑ[Group], ΜΕΓΑΛΟ[1].ΑΛΦΑ.Χ=10, ΜΕΓΑΛΟ[1].ΑΛΦΑ.Ψ=3
' ή αν έχει γίνει η Κάλεσε Μεγάλο και μετά η Κάλεσε Ένα
' Α[2].ΑΛΦΑ[Group], Α[2].ΑΛΦΑ.Χ=10, Α[2].ΑΛΦΑ.Ψ=3
' Το παρακάτω τυπώνει τιμή με χρήση δείκτη (σε αλφαριθμητικό),
' εδώ η Τμήμα$ έχει το τρέχον όνομα του τμήματος
Αναφορά Μορφή$("{0}.Αλφα.χ = {1}", Τμήμα$, Εκφρ(Τμήμα$.Άλφα.Χ))
Για Άλφα {
' Εδώ το = δεν έχει θέμα γιατί η Άλφα έχει φτιαχτεί με ορισμό Ομάδα εντός τμήματος
' Το τμήμα όμως είναι τμήμα Ομάδας
.χ=20
.ψ+=10
Λίστα
Αναφορά Μορφή$("Νέες τιμές Άλφα.χ και Άλφα.ψ = {0}, {1}",.χ, .ψ)
}
' το "μυστήριο" ξεκινάει εδώ, όπου το Ζήτα δημιουργείται από το Άλφα
' τα Ζήτα.χ και Ζήτα.ψ δεν έχουν πρόθεμα εσωτερικά το Τμήμα$
Ζήτα = Άλφα
Λίστα
Για Ζήτα {
Αναφορά Μορφή$("Ζήτα.χ και Ζήτα.ψ = {0}, {1}", .χ, .ψ)
}
' Όπότε η αλλαγή τιμής κανονικά γίνεται με <= σαν να είναι γενική
Δες οκ {
Αναφορά "Δοκιμή της Ζήτα.χ<=300"
Ζήτα.χ<=300
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
Δες οκ {
Αναφορά "Δοκιμή της Εκφρ(Τμήμα$.Ζήτα.χ)"
Αναφορά Μορφή$("{0}.Ζήτα.χ={1}", Τμήμα$, Εκφρ(Τμήμα$.Ζήτα.χ))
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
Τμήμα Κάπα {
Δες οκ {
Αναφορά "Δοκιμή της Ζήτα.χ εντός της Κάπα"
Αναφορά Μορφή$("Εντός Κάπα το Ζήτα.χ = {0} ", Ζήτα.χ)
}
Αν όχι οκ ή Λάθος τότε Αναφορά "Δίνει λάθος "+Λάθος$
' δίνει Όχι γιατί το Ζήτα δεν είναι γενικό!
Αναφορά Μορφή$("Έίναι έγκυρο το Ζήτα: {0}", Γραφή$(Έγκυρο(Ζήτα),{"Ναι";"Ναι";"Όχι"}) )
}
Κάπα
Ζήτα.χ=1000
Αναφορά Μορφή$("ΜεΖήτα.χ=1000 δώσαμε τιμή: {0}" , Ζήτα.χ)
Λίστα
Δέλτα=Ζήτα
Αναφορά Μορφή$("Η Δέλτα.χ έχει τη κανονική τιμή: {0}" , Δέλτα.χ)
Λίστα
}
' Τώρα καλούμε
Ένα
' Τώρα το καλούμε με την κάλεσε
Κάλεσε Ένα
}
Μεγάλο
Κάλεσε Μεγάλο
2.5. Ορισμός Κλάσης
Δείτε τι γίνεται τώρα: Με ένα αντικείμενο έχουμε τρία προγράμματα, ένα να ζητάει νούμερο, ένα άλλο να έχει τρία νούμερα και κάνει κάτι με αυτά όταν θέλει, και ένα ακόμα που κάνει επανάληψη βάσει σειράς "μηνυμάτων". Σε κάθε περίπτωση ασχολούμαστε με ένα αντικείμενο που δεν μας ενδιαφέρει πια πως είναι γραμμένο! Μάλιστα μπορώ να φτιάξω μια συνάρτηση που λέγεται κλάση και επιστρέφει ένα αντικείμενο και να δημιουργήσω με δυο κλήσεις δυο αντικείμενα:
Κλάση Αλφα1 {
Β=10, Α
Τμήμα ΚάνεΚάτι {
Τύπωσε .Α*2+.Β
.Β+=.Α*2
}
}
Άλφα=Αλφα1()
Για Άλφα {
Σωρός Νέος {
Σειρά 20, 30, 40
Ενώ όχι κενό {
Διάβασε .Α
.ΚάνεΚάτι
}
}
}
Βήτα=Αλφα1()
Για Βήτα {
Σωρός Νέος {
Σειρά 25, 45, 85
Ενώ όχι κενό {
Διάβασε .Α
.ΚάνεΚάτι
}
}
}
Η κλάση δεν δίνει τύπο στην Μ2000 δίνει απευθείας το αντικείμενο, αλλά γράφει σε αυτό τον τύπο με με όνομα το όνομα της κλάσης (χρήσιμο όταν ελέγχουμε για τύπο ομάδας). Ο ορισμός δημιουργεί μια συνάρτηση Αλφα1() και αυτή η συνάρτηση επιστρέφει μια ομάδα!Συντακτικά, δέχεται ένα όνομα (θα είναι γενικό μέχρι να διαγραφεί το τμήμα που την όρισε), και ονόματα άλλων κλάσεων που θέλουμε να συνυπάρχουν (μια μορφή κληρονομικόητας). Μέσα γράφουμε ότι θα γράφαμε και σε έναν ορισμό ομάδας. Ένας εσωτερικός ορισμός κλάσης είναι τοπικός, αλλά μπορεί να έχει και αυτός κληρονομίσει από άλλη κλάση (γενική). Δημιουργούμε ομάδες με ονόματα κλάσεων μέσα σε ομάδες (αν υπαρχει κατασκευαστής τον καλούμε, αλλά δεν θα το δούμε τώρα). Οι τετράγωνες αγκύλες σημαίνουν εδώ ότι βάζουμε όσα θέλουμε (δεν βάζουμε κόμμα).Κλάση Όνομα [ως Όνομα1] {[ Κλάση Εσωτερική [ως ΌνομαΧ] {}]Εσωτερική ΌνομαΟμάδας}Κλάση β {
α$="οκ"
}
Κλάση Άλφα {
Ένας_Αριθμός
Μ=100
Κλάση ΜΜ ως β {
β$="yes"
}
}
Μ->Άλφα
Τύπωσε Μ=>Λ είναι τύπος β
Τύπωσε Μ=>Λ.α$Το Μ είναι δείκτης αλλά το Λ δεν είναι, είναι επώνυμη ομάδα, μέλος της Μ. Μια ομάδα μπορεί να έχει άλλες ομάδες ως μέλη, άλλες σε καταχωρητές όπως πίνακες, λίστες, σωρούς τιμών, άλλες σε μέλη που είναι δείκτες σε ομάδες. Αυτές οι ομάδες που είναι μέλη, είναι σαν στατικές, δηλαδή θα είναι πάντα εκεί, ενώ σε κάθε άλλη περίπτωση οι ομάδες μπορούν να γίνουν τύπος Μηδενικός.
Αν θέλω μετά τη διαδικασία η Βήτα να έχει τα ίδια .Α και .Β με μια εντολή Βήτα=Αλφα το κάνω!
Δεν μπορούμε να συγκρίνουμε ομάδες (εκτός αν γυρνούν τιμή - δηλαδή έχουμε δώσε Αξία { }, ή έχουμε δώσει και τελεστή για σύγκριση, προχωρημένο θέμα).
Δεν μπορούμε να συγκρίνουμε ομάδες (εκτός αν γυρνούν τιμή - δηλαδή έχουμε δώσε Αξία { }, ή έχουμε δώσει και τελεστή για σύγκριση, προχωρημένο θέμα).
Υπάρχουν οι τελεστές Ειναι και Ειναι Τύπος, και μπορούμε να φτιάξουμε τελεστές σε ομάδες, οπότε αν φτιάξουμε το τελεστή "=" φτιάχνουμε μια ισότητα για αντικείμενα. Το Είναι κοιται αν δυο αντικείμενα έχουν τον ίδιο βασικό δείκτη, ενώ η Είναι Τύπος κοιτάει για ένα αντικείμενο αν είναι τύπος το όνομα που δίνουμε. Υπάρχει και η Έγκυρο() που με ένα τρόπο κοιτάει αν μια επώνυμη ομάδα έχει τα μέλη τουλάχιστον που έχει μια άλλη ομάδα (δεν κοιτάει για συναρτήσεις/τμήματα). Στο παράδειγμα οι Μ και Ζ δεν έχουν καθορισμένο τύπο, αλλά η Ζ μπορεί να χρησιμοποιηθεί ως Μ, ενώ το ανάποδο δεν γίνεται. Αυτός ο τρόπος είχε φτιαχτεί πριν μπουν οι τύποι στις ομάδες.ομάδα Μ {
χ=10
}
Τύπωσε Μ είναι τύπος μηδενικός=Ψευδές
ομάδα Ζ {
λ=30, χ=50
}
Τύπωσε Έγκυρο(@Ζ ως Μ)=Αληθές
Τύπωσε Έγκυρο(@Μ ως Ζ)=Ψευδές
Η Τύπωσε Α δίνει 0 αν έχουμε ομάδα και δεν έχουμε δώσει Αξία. Άρα εδώ πρέπει να φτιάξουμε το τρόπο που θα τις συγκρίνουμε.
Αν δώσω την εντολή:
Μπορώ να προσθέσω πράγματα με νέο ορισμό ή με συγχώνευση: Η αντικατάσταση στις ομάδες κάνει αντικατάσταση στα όμοια αλλά προσθέτει στην αριστερή ομάδα εκείνα που έχει η δεξιά και δεν έχει η αριστερή.
Βάλε Αλφα
Διάβασε Λάμδα
Λάμδα.Α=50
Λάμδα.ΚάνεΚάτι
Τώρα έχουμε μια Λάμδα ίδια με την Άλφα! Οι ομάδες γίνονται ανώνυμες και μπαίνουν στο σωρό.
Η .Β στην Άλφα ήταν 190 άρα θα πρέπει να πάρουμε 50*2+190, άρα 290. Δηλαδή όχι μόνο περάσαμε λειτουργικότητα στη Λάμδα αλλά σώσαμε την κατάσταση του Α.
Ενώ ξεκινήσαμε με απλά τμήματα, και με γενικές μεταβλητές, και έπρεπε τα ονόματα να έχουν μια "συνέπεια", να μην κάνουμε κάποιο λάθος και έχουμε μια τοπική ενώ θέλαμε μια γενική, με τα αντικείμενα πολλαπλασιάζουμε τις δυνατότητες να ενσωματώνουμε δεδομένα με λειτουργικότητα. Δεν μας ενδιαφέρει το τι γίνεται στο αντικείμενο αλλά ότι έχουμε με .Α ιδιότητα για να βάλουμε τιμή και μια μέθοδο .ΚάνεΚάτι
(Ιδιότητα είναι πια ξεχωριστή ομάδα σε ομάδα, ενώ οι απλές μεταβλητές όπως η Α είναι μεταβλητές που ή θα είναι ιδιωτικές ή δημόσιες αλλά δεν μπορούμε να ελέγχουμε αν θα παίρνουν μόνο τιμή, ή θα δίνουν μόνο τιμή, και αν θα έχουν ιδιότητες και μεθόδους και αυτές, όπως με τις ιδιότητες - μπήκαν από την 8.4 έκδοση)
"Όπου και να πάει το αντικείμενο Ομάδα θα έχει αυτά τα δύο, ιδιότητες και μεθόδους, ή με πιο γενική έννοια μέλη. Όπως και σε κάθε αντίγραφο!"
Είδαμε ότι στο τμήμα (και στις συναρτησεις/τμήματα γενικότερα) οι μεταβλητές της ομάδας μπορούν να εμφανιστούν (και αν αλλάξουμε με αντικατάσταση τιμή θέλουμε το σύμβολο <= όπως στις γενικές).
Από την έκδοση 8.4 έχουμε και ομάδες με ονόματα αλφαριθμητικού, δηλαδή με το $ στο τέλος, όπως και Κλάσεις με το ονόματα με το $ στο τέλος. Αυτό συμβαίνει ότι θέλουμε η ομάδα (και αυτή που γυρνάει από κλάση) να έχει Αξία αλφαριθμητικό.
Ακολουθεί ένα πρώτο παράδειγμα...με μια απλή ομάδα:
Ομάδα Άλφα$ {
Αξία {
="Ναι"
}
}
Τύπωσε Άλφα$ \\ δίνει Ναι
Δες {
Άλφα$="Όχι" \\ δεν έχουμε Θέσε { }
}
Τύπωσε Άλφα$ \\ δίνει Ναι
\\ Οι επώνυμες ομάδες αλλάζουν συναρτήσεις!
\\ Το ίδιο και οι ανώνυμες αν δεν βρίσκονται σε πίνακα που έγινε με αρχικοποίηση με ομάδα
Ομάδα Άλφα$ {
Αξία {
="Όχι"
}
}
Τύπωσε Άλφα$ \\ δίνει Όχι
Ακολουθεί ένα δεύτερο πιο ενισχυμένο!
Για δ(1) { Τύπωσε .Ν, "Οκ"}
Πίνακας π$(10) π$(2)=Ομάδα$(βητα$) π$(1)=Ομάδα$(αλφα$)
Ενωσε π$() στο π() π(1).Ν+=100 Τύπωσε π(1).Ν Τύπωσε π$(1)(2) Για ι=1 εως 5 {
Τύπωσε π$(1)(2), π$(2) } Για π(1) {
Τύπωσε .μετρητής } Για π(2) {
Τύπωσε .μετρητής }
2.6 Ανώνυμες (Πτητικές) Ομάδες
Η Μ2000 δεν σταματάει στα αντικείμενα ως ομάδες μεταβλητών με συναρτήσεις/τμήματα. Πάει ένα βαθμό παραπέρα!
Ο επόμενος βαθμός είναι τα αντικείμενα Ομάδες χωρίς όνομα. Αυτά τα αντικείμενα αντί για ένα ξεχωριστό όνομα το καθένα έχουν μια θέση σε έναν πίνακα, ή μια κατάσταση, ή σε ένα σωρό ή ως επιστροφή τιμής. Μπορούμε να έχουμε πολλούς πίνακες με πολλά αντικείμενα στον καθένα.
Χαρακτηριστικά για αντικείμενα (ομάδες) στους πίνακες είναι:
Μπορούμε να κρατήσουμε αντικείμενα με αντιγραφή στο σωρό ή σε πίνακα ή κάτι άλλο που έχει θέσεις που μπορούν να μπουν Ομάδες. Οι ανώνυμες ομάδες που επιστρέφονται λέγονται και πτητικές. (Έφυγαν από το τμήμα που σχηματίστηκαν).
Αν έχουμε μια ομάδα Α1 και θέλουμε ένα αντίγραφο σε ένα νέο όνομα έστω Β1 τότε αυτή η εκχώρηση:
Β1=Α1
θα δημιουργήσει ένα αντίγραφο του Α1 ως ανώνυμη ομάδα, και στην εκχώρηση ο Διερμηνευτής θα δει μια τιμή 0 και το αντικείμενο της "πτητικής" ομάδας. Τότε αποφασίζει πως θα φτιάξει ομάδα!
(ομολογώ ότι το προηγούμενο έκανα δέκα χρόνια να το σκεφτώ, γιατί είχα την ιδέα ότι μια παράσταση πρέπει να γυρνάει επακριβώς ένα πράγμα, έτσι ακριβώς το διαβάζουμε παντού, εσωτερικά όμως ο διερμηνευτής κοιτάει δυο αποτελέσματα όταν θέλει να εκχωρήσει τιμή σε μεταβλητή τύπου αριθμός)
(Επειδή από την 8.4 οι ομάδες μπορούν να γυρνούν τιμές έχουμε και την περίπτωση η Α1 να γυρνάει τιμή οπότε η Β1 δεν θα γίνει ομάδα αλλά αριθμητική μεταβλητή με την τιμή της ομάδας Α1, εκτός και αν το γνωρίζουμε και εκτελέσουμε την Β1=Ομαδα(Α1) οπότε σίγουρα η Β1 θα πάρει το αντίγραφο της Α1.
Ομοίως αν έχουμε μια κλάση Αλφα1() τότε στο παρακάτω (οι κλάσεις πάνταν δίνουν αντικείμενο ομάδα ακόμα και αυτό που φτιάχνουν θα έχει τιμή:
Α2=Αλφα1()
θα επιστραφεί το 0 και ένα αντικείμενο και ο διερμηνευτής θα αποφασίσει να φτιάξει το Α2 αν δεν είναι αντικείμενο ή να το συγχωνεύσει.
Φτιάχνοντας το Α2 σημαίνει να πάρει όλα τα μέλη της ανώνυμης ομάδας και να τους δώσει ονόματα (δεν σβήνουν πια).
Αν δώσω την εντολή:
Δέλτα=Άλφα
τότε φτιάχνω μια Δέλτα ως αντίγραφο της Άλφα και είναι ένα νέο αντικείμενο (με δική του κατάσταση από δω και μπρος). Δεν μπορώ να σβήσω αντικείμενα αν είναι επώνυμα.Μπορώ να προσθέσω πράγματα με νέο ορισμό ή με συγχώνευση: Η αντικατάσταση στις ομάδες κάνει αντικατάσταση στα όμοια αλλά προσθέτει στην αριστερή ομάδα εκείνα που έχει η δεξιά και δεν έχει η αριστερή.
Βάλε Αλφα
Διάβασε Λάμδα
Λάμδα.Α=50
Λάμδα.ΚάνεΚάτι
Τώρα έχουμε μια Λάμδα ίδια με την Άλφα! Οι ομάδες γίνονται ανώνυμες και μπαίνουν στο σωρό.
Η .Β στην Άλφα ήταν 190 άρα θα πρέπει να πάρουμε 50*2+190, άρα 290. Δηλαδή όχι μόνο περάσαμε λειτουργικότητα στη Λάμδα αλλά σώσαμε την κατάσταση του Α.
Ενώ ξεκινήσαμε με απλά τμήματα, και με γενικές μεταβλητές, και έπρεπε τα ονόματα να έχουν μια "συνέπεια", να μην κάνουμε κάποιο λάθος και έχουμε μια τοπική ενώ θέλαμε μια γενική, με τα αντικείμενα πολλαπλασιάζουμε τις δυνατότητες να ενσωματώνουμε δεδομένα με λειτουργικότητα. Δεν μας ενδιαφέρει το τι γίνεται στο αντικείμενο αλλά ότι έχουμε με .Α ιδιότητα για να βάλουμε τιμή και μια μέθοδο .ΚάνεΚάτι
(Ιδιότητα είναι πια ξεχωριστή ομάδα σε ομάδα, ενώ οι απλές μεταβλητές όπως η Α είναι μεταβλητές που ή θα είναι ιδιωτικές ή δημόσιες αλλά δεν μπορούμε να ελέγχουμε αν θα παίρνουν μόνο τιμή, ή θα δίνουν μόνο τιμή, και αν θα έχουν ιδιότητες και μεθόδους και αυτές, όπως με τις ιδιότητες - μπήκαν από την 8.4 έκδοση)
"Όπου και να πάει το αντικείμενο Ομάδα θα έχει αυτά τα δύο, ιδιότητες και μεθόδους, ή με πιο γενική έννοια μέλη. Όπως και σε κάθε αντίγραφο!"
Είδαμε ότι στο τμήμα (και στις συναρτησεις/τμήματα γενικότερα) οι μεταβλητές της ομάδας μπορούν να εμφανιστούν (και αν αλλάξουμε με αντικατάσταση τιμή θέλουμε το σύμβολο <= όπως στις γενικές).
2.5.1 Ορισμός κλάσης με όνομα αλφαριθμητικού
Από την έκδοση 8.4 έχουμε και ομάδες με ονόματα αλφαριθμητικού, δηλαδή με το $ στο τέλος, όπως και Κλάσεις με το ονόματα με το $ στο τέλος. Αυτό συμβαίνει ότι θέλουμε η ομάδα (και αυτή που γυρνάει από κλάση) να έχει Αξία αλφαριθμητικό.
Ακολουθεί ένα πρώτο παράδειγμα...με μια απλή ομάδα:
Ομάδα Άλφα$ {
Αξία {
="Ναι"
}
}
Τύπωσε Άλφα$ \\ δίνει Ναι
Δες {
Άλφα$="Όχι" \\ δεν έχουμε Θέσε { }
}
Τύπωσε Άλφα$ \\ δίνει Ναι
\\ Οι επώνυμες ομάδες αλλάζουν συναρτήσεις!
\\ Το ίδιο και οι ανώνυμες αν δεν βρίσκονται σε πίνακα που έγινε με αρχικοποίηση με ομάδα
Ομάδα Άλφα$ {
Αξία {
="Όχι"
}
}
Τύπωσε Άλφα$ \\ δίνει Όχι
Ακολουθεί ένα δεύτερο πιο ενισχυμένο!
Ομάδα
αλφα$ {
Ν=10
Ιδιότητα μετρητής {Αξία}
Αξία (πολ) {= Επαν$("οκ", πολ) : .[μετρητής]++} } Ομάδα βητα$ {
Ιδιότητα μετρητής {Αξία}
Αξία {= Επαν$("οκ", Τυχαίος(1, 5)): .[μετρητής]++} } Κατάσταση α=1:=Ομάδα$(αλφα$) , 2:=Ομάδα$(βητα$) Πινακας δ$(10) δ$(2)=Ομάδα$(βητα$) δ$(1)=Ομάδα$(αλφα$) Τύπωσε δ$(1)(5) Τύπωσε δ$(2)
Ν=10
Ιδιότητα μετρητής {Αξία}
Αξία (πολ) {= Επαν$("οκ", πολ) : .[μετρητής]++} } Ομάδα βητα$ {
Ιδιότητα μετρητής {Αξία}
Αξία {= Επαν$("οκ", Τυχαίος(1, 5)): .[μετρητής]++} } Κατάσταση α=1:=Ομάδα$(αλφα$) , 2:=Ομάδα$(βητα$) Πινακας δ$(10) δ$(2)=Ομάδα$(βητα$) δ$(1)=Ομάδα$(αλφα$) Τύπωσε δ$(1)(5) Τύπωσε δ$(2)
Για δ(1) { Τύπωσε .Ν, "Οκ"}
Πίνακας π$(10) π$(2)=Ομάδα$(βητα$) π$(1)=Ομάδα$(αλφα$)
Ενωσε π$() στο π() π(1).Ν+=100 Τύπωσε π(1).Ν Τύπωσε π$(1)(2) Για ι=1 εως 5 {
Τύπωσε π$(1)(2), π$(2) } Για π(1) {
Τύπωσε .μετρητής } Για π(2) {
Τύπωσε .μετρητής }
2.6 Ανώνυμες (Πτητικές) Ομάδες
Η Μ2000 δεν σταματάει στα αντικείμενα ως ομάδες μεταβλητών με συναρτήσεις/τμήματα. Πάει ένα βαθμό παραπέρα!
Ο επόμενος βαθμός είναι τα αντικείμενα Ομάδες χωρίς όνομα. Αυτά τα αντικείμενα αντί για ένα ξεχωριστό όνομα το καθένα έχουν μια θέση σε έναν πίνακα, ή μια κατάσταση, ή σε ένα σωρό ή ως επιστροφή τιμής. Μπορούμε να έχουμε πολλούς πίνακες με πολλά αντικείμενα στον καθένα.
Χαρακτηριστικά για αντικείμενα (ομάδες) στους πίνακες είναι:
- η εκχώρηση Ομάδας διαγράφε την υπάρχουσα Ομάδα. Δεν έχουμε συγχώνευση όπως με τα επώνυμα αντικείμενα τύπου Ομάδας.
- Ένα ανώνυμο αντικείμενο Ομάδα μπορεί να γίνει πρόσκαιρα επώνυμο, χωρίς να γνωρίζουμε το επιλεγμένο όνομα. Και έτσι χειριζόμαστε τα μέλη του
- Ένα ανώνυμο αντικείμενο τύπου Ομάδα διαγράφεται με την αλλαγή του με άλλο, ή με την καταστροφή του χώρου που το φιλόξενεί.
- Ένα ανώνυμο αντικείμενο τύπου Ομάδα μπορεί να βρίσκεται και στο σωρό και σε αντικείμενο σωρού, και σε Κατάσταση (λίστα με κλειδί).
- Ένα ανώνυμο ανιτκείμενο τύπου Ομάδα μπορεί να έχει πίνακες/καταστάσεις/σωρούς με ανώνυμα αντικείμενα Ομάδες, που να έχουν πίνακες/καταστάσεις/σωρούς με ανώνυμα αντικείμενα Ομάδες.
- Δεν γίνεται δύο διαφορετικές θέσεις να δείχνουν την ίδια ομάδα, εκτός αν κάνουμε χρήση δεικτών.
Μπορούμε να κρατήσουμε αντικείμενα με αντιγραφή στο σωρό ή σε πίνακα ή κάτι άλλο που έχει θέσεις που μπορούν να μπουν Ομάδες. Οι ανώνυμες ομάδες που επιστρέφονται λέγονται και πτητικές. (Έφυγαν από το τμήμα που σχηματίστηκαν).
Αν έχουμε μια ομάδα Α1 και θέλουμε ένα αντίγραφο σε ένα νέο όνομα έστω Β1 τότε αυτή η εκχώρηση:
Β1=Α1
θα δημιουργήσει ένα αντίγραφο του Α1 ως ανώνυμη ομάδα, και στην εκχώρηση ο Διερμηνευτής θα δει μια τιμή 0 και το αντικείμενο της "πτητικής" ομάδας. Τότε αποφασίζει πως θα φτιάξει ομάδα!
(ομολογώ ότι το προηγούμενο έκανα δέκα χρόνια να το σκεφτώ, γιατί είχα την ιδέα ότι μια παράσταση πρέπει να γυρνάει επακριβώς ένα πράγμα, έτσι ακριβώς το διαβάζουμε παντού, εσωτερικά όμως ο διερμηνευτής κοιτάει δυο αποτελέσματα όταν θέλει να εκχωρήσει τιμή σε μεταβλητή τύπου αριθμός)
(Επειδή από την 8.4 οι ομάδες μπορούν να γυρνούν τιμές έχουμε και την περίπτωση η Α1 να γυρνάει τιμή οπότε η Β1 δεν θα γίνει ομάδα αλλά αριθμητική μεταβλητή με την τιμή της ομάδας Α1, εκτός και αν το γνωρίζουμε και εκτελέσουμε την Β1=Ομαδα(Α1) οπότε σίγουρα η Β1 θα πάρει το αντίγραφο της Α1.
Ομοίως αν έχουμε μια κλάση Αλφα1() τότε στο παρακάτω (οι κλάσεις πάνταν δίνουν αντικείμενο ομάδα ακόμα και αυτό που φτιάχνουν θα έχει τιμή:
Α2=Αλφα1()
θα επιστραφεί το 0 και ένα αντικείμενο και ο διερμηνευτής θα αποφασίσει να φτιάξει το Α2 αν δεν είναι αντικείμενο ή να το συγχωνεύσει.
Φτιάχνοντας το Α2 σημαίνει να πάρει όλα τα μέλη της ανώνυμης ομάδας και να τους δώσει ονόματα (δεν σβήνουν πια).
Στο παράδειγμα, στις θέσεις Μ(2) και Μ(3) έχουμε το ίδιο αντικείμενο. Δείτε εδώ στους πίνακες δεν χρησιμοποιούμε τα => για τα μέλη των αντικειμένων, αλλά την τελεία.
Ομάδα Α {
χ=5, ψ=10
Συνάρτηση ΧΨ {
=.χ*.ψ
}
}
Πίνακας Μ(10)
Μ(3)=Α
Μ(2)->Μ(3)
Τύπωσε Α.ΧΨ()=50, Μ(3).ΧΨ()=50, Μ(2).ΧΨ()=50
Α.Χ+=10
Τύπωσε Α.ΧΨ()=150, Μ(3).ΧΨ()=50, Μ(2).ΧΨ()=50
Μ(2).Χ+=20
Τύπωσε Α.ΧΨ()=150, Μ(3).ΧΨ()=250, Μ(2).ΧΨ()=250
Μ(3).Χ-=20
Τύπωσε Α.ΧΨ()=150, Μ(3).ΧΨ()=50, Μ(2).ΧΨ()=50
2.7 Μπλοκ προσωρινής δημιουργίας ορισμών
Η Μ2000 έχει ένα τρόπο για προσωρινή δημιουργία επώνυμων αντικειμένων από ανώνυμα. Ότι φτιαχτεί σε αυτό το χώρο, επώνυμο, θα διαγραφεί στο πέρας του. Όμως μπορούμε να χρησιμοποιήσουμε τη δομή και για άλλες περιπτώσεις αρκεί να μην δώσουμε το πτητικό αντικείμενο αλλά ή ένα επώνυμο ή το Αυτό, το τμήμα αν δεν είμαστε σε τμήμα αντικειμένου ή το αντικείμενο.
ι=100
Για Αυτό {
Τοπική ι=10
Τύπωσε ι
}
Τύπωσε ι \100
ή σε τμήμα (δείχνω και ένα ανώνυμο τμήμα)
Ομάδα Αλφα {
ι=100
Τμήμα κοίτα {
Για Αυτό {
Τοπική ι=10
Τύπωσε ι, .ι \ 10 100
}
Τύπωσε .ι, έγκυρο(ι) \ 100 0
}
}
Άλφα.Κοίτα
\\ φτιάχνω κενό πίνακα
Πίνακας Α(10)
\\ βάζω στο 1 αντίγραφο του Άλφα
Α(1)=Άλφα
Α(1).Κοίτα
Και εδώ το τελικό πρόγραμμα:
Κλάση ΧΥΖ {
Χ=100, Υ=100, Ζ
Τμήμα ΠάρεΧΥΖ {
Διάβασε .Χ, .Υ, .Ζ
}
Συνάρτηση Μηδέν {
=.Χ=0 και .Υ=0 και .Ζ=0
}
}
Πίνακας Σ(100)=ΧΥΖ()
Για Σ(3) {
.Χ=0
.Υ=0
Τύπωσε .Μηδέν() \\ -1 αληθές
}
ΣύγκρινεΧΥΖ(1,3) \\ 0 δεν είναι ίδια
Σ(1)=Σ(3)
ΣύγκρινεΧΥΖ(1,3) \\ -1 είναι ίδια
Σ(8).ΠάρεΧΥΖ 20,40,50
ΔείξεΧΥΖ(8)
Τέλος
Ρουτίνα ΣύγκρινεΧΥΖ(α,β)
Για Σ(α),Σ(β) {
Τύπωσε .Χ==..Χ και .Υ==..Υ και .Ζ==..Ζ
}
Τέλος Ρουτίνας
Ρουτίνα ΔείξεΧΥΖ(α)
Για Σ(α) {
Τύπωσε μορφή$("το αντικείμενο {0} έχει τιμή({1},{2},{3})",α,.Χ, .Υ, .Ζ)
}
Τέλος Ρουτίνας
Εδώ έχουμε χρησιμοποιήσει ρουτίνες. Οι ρουτίνες δεν είναι τμήματα αλλά μέρη τμήματος που και αυτά έχουν την ιδιότητα να φτιάχνουν προσωρινά πράγματα (ανήκουν όμως στο ίδιο αντικείμενο εκτέλεσης και στο ίδιο όνομα χώρου, εκεί που κλήθηκαν,ενώ ως ορισμοί μπορει να βρίσκονται ακόμα και έξω από το τμήμα, αρκει να είναι στο ίδιο αρχικό τμήμα - όπως φορτώθηκε στο διερμηνευτή, γιατί ο διερμηνευτής την αναζητεί πρωτα στο τμήμα και μετά στο αρχικό κώδικα που ορίστηκε το τμήμα, πάντα στη πρώτη κλήση, μετά ξέρει που είναι). Τα ονόματά τους δεν καταχωρούνται όπως τα τμήματα και κανονικές συναρτήσεις ως οντότητες, οπότε πρέπει να δίνονται ως έχουν (κεφαλαία, πεζά και τόνοι) (στις νεότερες εκδόσεις μόνο οι τόνοι έχουν θεμα, καταχωρούνται με την πρώτη ζήτηση, στο αντικείμενο εκτέλεσης, δεν αλλάζουν ορισμό, ειναι στατικοί ορισμοί). Οι φωλιασμένες Για "αθροίζονται" ανά τμήμα/συνάρτηση (ανά ασντικείμενο εκτέλεσης) με συνέπεια αν χρησιμοποιήσουμε μια ρουτίνα να πρέπει να το μετρήσουμε και αυτό για τη χρήση των τελειών. Αν θέλουμε να το αποφύγουμε βάζουμε μια εργασία με ρουτίνες σε τμήμα. Βέβαια εδώ είναι εύλογο το ερώτημα...Πώς περνάμε ομάδες σε τμήματα;
Στο Για Σ(3) { } η ομάδα (αντικείμενο) στο Σ(3) έγινε επώνυμο, και έτσι μπορούμε να διαβάσουμε μαζικά, ή να αλλάξουμε μαζικά.
Το Σ(8).ΠάρεΧΥΖ 20,40,50 άνοιξε το Σ(8) πρόσκαιρα, κάλεσε την ΠάρεΧΥΖ και στην επιστροφή μάζεψε το αντικείμενο. Οπότε και στις δυο περιπτώσεις υπήρχε ανοιγμένο αντικείμενο που διαγράφτηκε.
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου
You can feel free to write any suggestion, or idea on the subject.