Κυριακή, 17 Απριλίου 2016

Ανοικτό και Κλειστό Αντικείμενο (Παραδείγματα)


Διαβάστε το κώδικα. Εξηγεί διάφορα θέματα για τα αντικείμενα και ειδικά τι είναι Ανοικτό και τι Κλειστό αντικείμενο (έχουν νόημα αυτές οι έννοιες στη Μ2000)
Σε κλασικές γλώσσες ένα αντικείμενο είναι ένα απλά αντικείμενο κατασκευασμένο και μια μεταβλητή κρατάει μια αναφορά σε αυτό. Στη Μ2000 τα αντικείμενα δεν είναι έτσι, τουλάχιστον όχι αυτά που λέμε Ομάδες ή Group. Δεν χρησιμοποιούμε δείκτες σε αντικείμενα. Τα ονόματα των αντικειμένων τα βλέπουμε όπως και τις μεταβλητές. Οπωσδήποτε εσωτερικά υπάρχει αναφορά, αλλά δεν μπορούν να πάρουν δεύτερη αναφορά. Τα κλειστά αντικείμενα είναι ανώνυμα, έχουν μόνο θέση, και μπορούν να μετακινηθούν, δηλαδή να φύγουν από εκεί που δημιουργήθηκαν (λέγονται και πτητικά). Π.χ. αν μια συνάρτηση επιστρέφει ένα αντικείμενο τότε αυτό είναι ανώνυμο. Αν εμείς του δώσουμε όνομα ή το συχγωνεύσουμε σε υπάρχον τότε χάνεται το ανώνυμο και έχουμε ένα ανοικτό αντικείμενο. Γίνεται να διατηρούμε και να χειριζόμαστε κλειστά αντικείμενα. Με τον τρόπο αυτό φαίνεται σαν να δουλεύουμε με δείκτες, αλλά στην ουσία είναι χειρισμός με τιμή (by value).


\\ Ανοιχτό Αντικείμενο
\\ Δημιουργία με ιδιωτικά και δημόσια στοιχεία
\\
\\ η μεταβλητή Άλφα είναι αντικείμενο τύπου Group (το λέμε Ομάδα).
\\ Ως ανοιχτό αντικείμενο κρατάει μόνο την λίστα των μελών του, μεταβλητές/πίνακες/τμήματα/συναρτήσεις
\\ Αυτή η λίστα είναι ανοιχτή. Μπορούμε να προσθέτουμε δηλαδή.
\\ Τα αντικείμενα για το λόγο αυτό δεν έχουν τύπο άλλο από τον γενικό τύπο Ομάδα ή Group


Ομάδα Άλφα {
Ιδιωτικό:
      Α, Β
Δημόσιο:
      Τμήμα ΜέθοδοςΑ {
            \\ αν έχουμε δυο αριθμούς φορτώνουμε τα Α και Β
            Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
            Τύπωσε "Κατάσταση Α:",*50+
      }
      Συνάρτηση ΙδιότηταΑ {
            =
      }
}


\\ Το παρακάτω δίνει Group κα 2 ( το 2 για τις ιδιωτικές μεταβλητές- δεν δίνει αριθμό τμημάτων-συναρτήσεων)
Τύπωσε Τύπος$(Άλφα), Ομάδα.Σύνολο(Άλφα)


Άλφα.ΜέθοδοςΑ 100,30 \\ δίνει 5030
Τύπωσε Άλφα.ΙδιότηταΑ() \\ δίνει 100
Τύπωσε Γραφή$(Έγκυρο(Άλφα.Α) , {;"Έγκυρο";"Μη Έγκυρο";}) \\ Μη έγκυρο
Τύπωσε Γραφή$(Έγκυρο(Άλφα.ΙδιότηταΑ()) , {;"Έγκυρο";"Μη Έγκυρο";}) \\ Έγκυρο


\\ Στο ανοιχτό αντικείμενο  τα μέλη/στοιχεία του είναι μεταβλητές/συναρτήσεις του τμήματος.
\\ όπως και κάθε μεταβλητή/συνάρτηση που κάνουμε σε αυτό.
\\ η διαφορά είναι ότι οι συναρτήσεις/τμήματα γνωρίζουν το όνομα του αντικειμένου που ανήκουν
\\ οπότε οι μεταβλητές με μόνο τελεία στην αρχή αναφέρονται σε αυτό το όνομα
\\ η .Α αναφέρεται στην Άλφα.Α αλλά επειδή είναι ιδιωτική δεν εμφανίζεται άμεσα στο τμήμα


\\ Παρόλο που λέγονται ιδιωτικές οι Α και Β μπορούμε να βάλουμε κάτι σε αυτές
\\ με την χρήση συμπληρωματικού ορισμού.
Ομάδα Άλφα { Ιδιωτικό: Α=30, Β=50}
Άλφα.ΜέθοδοςΑ  \\1550
Δες Οκ {
      Άλφα.Α+=100
}
\\ το Οκ γίνεται ψευδές αν έχουμε λάθος στο επίπεδο του μπλοκ, εδώ έχουμε εντολή σε επίπεδο του μπλοκ
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Δεν υπάρχει τέτοια μεταβλητή



\\ Σκοπός των ιδιωτικών μεταβλητών/συναρτήσεων κ.α. είναι να μην χρησιμοποιούνται από λάθος.
\\ Μπορούμε όμως αν θέλουμε να πάρουμε τις δυο πρώτες μεταβλητές ως αναφορές στις ΑΑ και ΒΒ
Διάβασε από Άλφα, ΑΑ, ΒΒ
\\ οι ΑΑ και ΒΒ είναι αναφορές στις ιδιωτικές μεταβλητές Α και Β, αν αλλάξουν αλλάζουν και τα Α και Β
Τύπωσε ΑΑ, ΒΒ
Στη ΑΑ=500, ΒΒ=100
Άλφα.ΜέθοδοςΑ  \\ 25100
Άλφα.ΜέθοδοςΑ 500, 100 \\ 25100



\\ Αντιγραφή και Συγχώνευση Ανοικτών Αντικειμένων
\\ ένα ανοικτό αντικείμενο μπορεί να αντιγραφεί κάπου αλλου, εδώ σε ένα νέο
\\ μαζί με τις ιδιωτικές μεταβλητές.
\\ Εδώ το Άλφα έδωσε ένα κλειστό, ανώνυμο αντικείμενο το οποίο γράφτηκε ως Βήτα.
\\ το Βήτα είναι πια ανοικτό αντικείμενο όμως μεσολάβησε το κλείσιμο και η τελική αντιγραφή


Βήτα=Άλφα
Βήτα.ΜέθοδοςΑ \\ 25100
Στη ΑΑ=30, ΒΒ=50
Άλφα.ΜέθοδοςΑ \\ 1550
\\ στη Βήτα οι Α και Β είναι νέες ιδιωτικές τιμές, η αντιγραφή δίνει νέα ονόματα αλλά ίδιες τιμές
Βήτα.ΜέθοδοςΑ   \\ 251000


\\ Μπορώ να προσθέτω μεθόδους
Ομάδα Βήτα {
      Τμήμα ΜέθοδοςΒ {
      Τύπωσε "Κατάσταση Β:",*30+*10
       }
}
Βήτα.ΜέθοδοςΒ  \\ 16000
\\ μπορώ να συγχωνεύω αντικείμενο σε άλλο, αυτή είναι μια αντιγραφή σε όμοια:
Βήτα=Άλφα
Βήτα.ΜέθοδοςΒ   \\ 1400
Δες Οκ {
      Άλφα.ΜέθοδοςΒ
}
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Άγνωστο τμήμα ΑΛΦΑ.ΜΕΘΟΔΟΣΒ"
\\ τώρα θα τα κάνουμε ίσα, αφού αντιγράφουμε το Βήτα στο Άλφα,
\\  και του δίνουμε και αυτό που δεν έχει! Δηλαδή ένα αντικείμενο αναβαθμίζει ένα άλλο.
Άλφα=Βήτα
Άλφα.ΜέθοδοςΒ  \\ 1400
\\ Στη Μ2000 δεν μπορούμε να σβήσουμε μέλη του αντικειμένου
\\ Μπορούμε να φτιάξουμε πρόσκαιρα όμως, και να τα χρησιμοποιήσουμε
\\ Όπως εδώ φτιάχνουμε ένα τμήμα για μια φορά!
Ομάδα Έψιλον {
Ιδιωτικό:
      Α, Β
}
Για Έψιλον {
      Ομάδα Αυτό {
              Τμήμα Μιαφορά {
                    Διάβασε .Α,
              }
      }
      .Μιαφορά 123, 56
}
Διάβασε από Έψιλον, Εψ.Α, Εψ.Β
Τύπωσε Εψ.Α, Εψ.Β '123, 56
Δες Οκ {
      Έψιλον.Μιαφορα 10, 50
}
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Άγνωστο τμήμα ΕΨΙΛΟΝ.ΜΙΑΦΟΡΑ"


Άλφα=Έψιλον \\ του έδωσε μόνο τις τιμές Α και Β
Άλφα.ΜέθοδοςΑ  \\ 6206


\\ Μπορούμε να δημιουργούμε συναρτήσεις που δίνουν ανώνυμα τμήματα (κλειστά)
\\ Εδώ η επιστροφή του κλειστού αντικειμένου συγχωνεύεται με το Άλφα (και αλλάζει το κώδικα του τμήματος)


Κλάση ΑναβάθμισηΑ {
            Τμήμα ΜέθοδοςΑ {
                  Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
                  Τύπωσε "Νέα Κατάσταση Α:",*5000+*100
            }
}
Άλφα=ΑναβάθμισηΑ()
Άλφα.ΜέθοδοςΑ  \\ 620600


\\ Μπορούμε να φτιάχνουμε ομάδες με χρήση της κλάσης και να δίνουμε αρχικές τιμές
Κλάση ΣανΤηνΆλφα {
Ιδιωτικό:
      Α, Β
Δημόσιο:
      Τμήμα ΣανΤηνΆλφα {
            Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
      }
      Τμήμα ΜέθοδοςΑ {
            \\ αν έχουμε δυο αριθμούς φορτώνουμε τα Α και Β
            Αν Ταύτιση("ΑΑ") Τότε Διάβασε,
            Τύπωσε "Κατάσταση Α:",*50+
      }
      Συνάρτηση ΙδιότηταΑ {
            =
      }
}
Άλφα=ΣανΤηνΆλφα(100,50)
Άλφα.ΜέθοδοςΑ  \\ 5050


\\ όμως έχει μείνει η μέθοδοςΒ
Άλφα.ΜέθοδοςΒ  \\ 3050


Άλφα.ΣανΤηνΆλφα 30,30 \\ μπορώ τον κατασκευαστή να τον χρησιμοποιώ όποτε θέλω
Άλφα.ΜέθοδοςΑ  \\ 1530
\\ μπορούμε να δούμε τι τμήματα και τι συναρτήσεις είναι αυτό το τμήμα
\\ αν το τμήμα λέγεται Α θα δούμε τα Α.ΑΛΦΑ.ΜΕΘΟΔΟΣΑ, Α.ΑΛΦΑ.ΙΔΙΟΤΗΤΑΑ( και άλλα
\\ δηλαδή θα μας δείξει κάθε μέλος της κάθε ομάδας σαν χωριστές οντότητες και οι ομάδες χωριστά.
\\ Σε άλλες γλώσσες τα αντικείμενα είναι ένα πακέτο, εδώ είναι πιο χαλαρή η έννοια
\\ είναι μια λίστα οντοτήτων που κάνουμε προσθήκη, αντιγραφή ή και συγχώνευση.
\\ και μπορούμε να περνάμε με αναφορά σε κλήσεις τμημάτων συναρτήσεων.
\\ η δε αντιγραφή δημιουργεί το κλειστό αντικείμενο.


Τμήματα ?
Συνάρτηση ΚάνεΚάτι {
      Διάβασε Κάτι
      Κάτι.ΣανΤηνΑλφα 1000, 20
      \\ εδώ επιστρέφουμε κλειστό αντικείμενο, ανώνυμο
      \\ η ομάδα Κάτι θα χαθεί, όχι όμως το κλειστό αντικείμενο
      =Κάτι
}


Άλφα=ΚάνεΚάτι(Άλφα)
Άλφα.ΜέθοδοςΑ  \\ 50020


\\ Τώρα θα περάσουμε με αναφορά το αντικείμενο
Τμήμα ΚάνεΚάτι2 {
      Διάβασε &Κάτι
      \\ δημιουργούνται όλα τα μέλη της Άλφα με αναφορά με όνομα Κάτι
      \\ τα τμήματα μόνο μαζί με το αντικείμενο μπορούν να περάσουν
      \\ με αναφορά
      Κάτι.ΣανΤηνΑλφα 500, 10
}
ΚάνεΚάτι2 &Αλφα
Άλφα.ΜέθοδοςΑ  \\ 25010


\\ μπορούμε να περάσουμε με αναφορά μια συνάρτηση του Άλφα
\\ χωρίς να περάσουμε το αντικείμενο. (μόνο οι συναρτήσεις το κάνουν αυτό)
Τμήμα ΚάνεΚάτι3 {
      Διάβασε &ΙδιότηταΜόνο()
      Τύπωσε ΙδιότηταΜόνο() \500
}
ΚάνεΚάτι3 &Αλφα.ΙδιότηταΑ()


\\ Αυτό εδώ είναι προχωρημένο!
\\ Αντί για χρήση αναφοράς - που δημιουργεί όλα τα μέλη με αναφορά
\\ μπορούμε να χρησιμοποιήσουμε δείκτη, ως ισχνή αναφορά
Δείκτης$=Ισχνή$(Άλφα)


Τμήμα ΚάνεΚάτι4 {
      Διάβασε Δ$
      Δ$.ΣανΤηνΑλφα 150, 5
      Τύπωσε Συνάρτηση(Δ$.ΙδιότηταΑ()) \\ 500
      Για Δ$ {
            Τύπωσε .ΙδιότηταΑ() \\ 500
            .ΜέθοδοςΑ  \\ 7505
      }
      Τύπωσε Δ$ \\ αν το Άλφα είναι στο Α τυπώνει Α.ΑΛΦΑ
}
ΚάνεΚάτι4 Δείκτης$
Δείκτης$.ΜέθοδοςΑ \\ 7505
Τύπωσε Τμήμα$+".ΑΛΦΑ"=Ισχνή$(Άλφα) \\ -1 δηλαδή Αληθές
\\ το όνομα του τμήματος μπορεί να είναι Α αλλά αν το τμήμα κληθεί με Κάλεσε θα αλλαξει όνομα
\\ έτσι δεν φτιάχνουμε δείκτες με το όνομα που δίνουμε, αλλά αφήνουμε την Ισχνή$() να το δημιουργήσει
\\ την ώρα της εκτέλεσης.


\\ Κλειστό (ανώνυμο) αντικείμενο δημιουργούμε στο σωρό:
Για Αυτό {
      \\ στο μπλοκ Για Αυτό {} θα υπάρχουν οι Κάπα και Μι μετά χάνονται
      \\ βάζουμε αντίγραφα ως κλειστά αντικείμενα στο σωρό τιμών
      Βάλε Αλφα, Αλφα
      \\ διαβάζουμε τα κλειστά σε ανοιχτά
      Διάβασε Κάπα, Μι
      Κάπα.ΜέθοδοςΑ
      Μι.ΜέθοδοςΑ
}
\\ Κλειστά αντικείμενα μπαίνουν και σε πίνακα
Πίνακας Α(10)
Βάλε Άλφα, Άλφα
Διάβασε Α(0), Α(1)
\\ Μπαίνουν απευθείας
\\ Στους πίνακες δεν γίνεται ποτέ συγχώνευση, αλλά μόνο αντικατάσταση του παλιού από το νέο.
Α(3)=Άλφα
Α(0).ΜέθοδοςΑ \\ 7505
Α(1).ΜέθοδοςΒ \\ 4550
\\ Η Μ2000 δεν έχει αναφορές ξεχωριστές για στοιχεία πίνακα. Μπορεί να φτιάξει ισχνή αναφορά όμως
\\ και είναι η μόνη περίπτωση που δέχεται ανοικτό ή κλειστό αντικείμενο για πέρασμα σε τμήμα
ΚάνεΚάτι4 Ισχνή$(Α(3))


\\ Ο πίνακας αντιγράφεται με όλα τα κλειστά αντικείμενα (όχι με αναφορές στα αντικείμενα)
\\ Ο νέος πίνακας πρέπει να δηλωθεί πριν
\\ (όλοι οι πίνακες στη Μ2000 είναι δυναμικοί, μεγαλώνουν ή μικραίνουν όπως θέλουμε)
\\ μετά θα μπορούσα να βάλω Π()=Α()
Βάλε Α()
Πίνακας Π()
Διάβασε Π()
\\ δεν έχουμε συγχώνευση μεταξύ κλειστών αντικειμένων
\\ αριστερά είναι κλειστό γιατί είναι σε πίνακα
\\ δεξιά είναι κλειστό γιατί είναι επιστροφή από συνάρτηση.
\\ μόνο αν το αριστερό ήταν ανοικτό θα γίνοταν συγχώνευση
Α(3)=ΣανΤηνΆλφα(20,20)
Δες Οκ {
      Α(3).ΜέθοδοςΒ
}
Αν όχι Οκ τότε Τύπωσε Λάθος$ \\ τυπώνει "Άγνωστο τμήμα"
Α(3).ΜέθοδοςΑ \\ 1020
Π(3).ΜέθοδοςΑ \\ 7505
Α()=Π()
Α(3).ΜέθοδοςΑ \\ 7505  '' όχι μόνο αντιγράψαμε το Α(3) αλλά ότι είχε ο πίνακας Π()!
\\ Για να κάνουμε συγχώνευση πρέπει προσωρινά να δουλέψουμε στο ανοικτό
\\ με την Για {} δουλεύουμε πάντα σε ανοικτό αντικείμενο
Για Α(1) {
      Αυτό=ΣανΤηνΆλφα(20,20)
}
Α(1).ΜέθοδοςΒ \\ 800
\\ εκτός από την χρήση του δείκτη μπορούμε να περάσουμε το ανοικτό αντικείμενο
\\ θα γίνουν αλλαγές και θα κλείσει ξανά
Για Α(0) {
      ΚάνεΚάτι2 &Αυτό
}
\\ Εδώ φαίνεται σαν να είναι ανοικτό, αλλά ανοίγει άμεσα εκτελείται και μετά κλείνει.
Α(0).ΜέθοδοςΑ \\ 25010


\\ μια ομάδα μπορεί να την συλλάβει μια λάμδα συνάρτηση
\\ αυτή η άλφα θα είναι μια νέα, ένα κλειστό αντικείμενο
\\ που θα ανοίγει όταν εκτελείται η λάμδα και θα κλείνει στο πέρας αυτού
Λ=Λάμδα Άλφα -> { Άλφα.ΜέθοδοςΑ Αριθμός, Αριθμός}
Κάλεσε Λ(30,30) \\ 1530
\\ και μια λάμδα συνάρτηση μπορεί να την συλλάβει μια άλλη
Κ=Λάμδα Λ->{Κάλεσε Λ(Αριθμός,20)}
Κάλεσε Κ(100) \\ 5020
Τμήμα ΚάτιΆλλο {
      Διάβασε Λ1
      Κάλεσε Λ1(20)
}
\\ αντί να περάσω τη Κ πέρασα κατευθείαν μια Λάμδα, χωρίς όνομα!
ΚάτιΆλλο Λάμδα Λ->{Κάλεσε Λ(Αριθμός, 10)} \\ θα δώσει 1010
ΚάτιΆλλο Κ \\ 1020


\\ Μια ομάδα μπορεί να έχει λάμδα συναρτήσεις και γεγονότα αλλά αυτό σε άλλη ανάρτηση!




Στο παραπάνω παράδειγμα η Λ μπορεί να γραφτεί και έτσι:
Λ=Λάμδα Άλφα -> { Άλφα.ΜέθοδοςΑ }

Δηλαδή χωρίς το πέρασμα Αριθμός, Αριθμός
αυτό γίνεται γιατί η κλήση τμημάτων γίνεται με κοινό σωρό τιμών. Η Αριθμός παίρνει τον αριθμό από την κορυφή του σωρού. Η κλήση  της μεθόδου με δυο παραμέτρους βάζει στο σωρό δυο τιμές με πρώτη τιμή στη κορυφή αυτήν που έχουμε αριστερά δηλαδή παίρνει το διερμηνευτής τις παραμέτρους τις βάζει σε μια στοίβα FIFO (το πρώτο που μπαίνει το πρώτο θα βγει), και κάνει συγχώνευση της λίστας με τον σωρό τιμών, ως πρώτο μέρος αυτού. Αν βάλουμε το Αριθμός, Αριθμός τότε θα φτιαχτεί μια στοίβα με το πρώτο και μετά το δεύτερο του σωρού τιμών και μετά θα συγχωνευθεί με αυτόν και πάλι θα έχουμε πρώτο στοιχείο αυτό που είχαμε και δεύτερο αυτό που είχαμε. Αν λοιπόν δεν βάλουμε το Αριθμός, Αριθμός τότε αφήνουμε το σωρό όπως πρέπει να είναι!
Οι συναρτήσεις αν κληθούν με την κάλεσε "παντρεύονται" το σωρό του τμήματος που τις κάλεσε. αν  όμως κληθούν σε παράσταση τότε έχουν δικό τους σωρό.

Ο λόγος που οι συναρτήσεις και τα τμήματα δεν έχουν περιγραφή του τι παραμέτρους παίρνουν είναι απλός. Παίρνουν οτιδήποτε αποφασίσει το πρόγραμμά μας, δηλαδή ότι εμείς θέλουμε.  Επιπλέον τα τμήματα μπορούν να αφήσουν τιμές στο σωρό. Πρακτικά όλα τα τμήματα έχουν το σωρό για είσοδο και έξοδο τιμών. Στο σωρό μπαίνει οτιδήποτε εκτός από αντικείμενα που δεν αντιγράφονται όπως τα αντικείμενα Gui και τα Com.

Δικό τους σωρό έχουν τα νήματα, ενώ οι ρουτίνες έχουν τον σωρό του τμήματος ή συνάρτησης που βρίσκονται. Μια αναδρομική διαδικασία σε ρουτίνα θα έχει πρόσβαση στον ίδιο σωρό, ενώ σε συνάρτηση σε χωριστό. Σε μια συνάρτηση αν δώσουμε επιπλέον παραμέτρους θα χαθούν στο πέρας της εκτέλεσης, δεν θα βγει λάθος. Μια ρουτίνα που περιγράφει το είδος και τον αριθμό στοιχείων εισόδου, ουσιαστικά είναι ψεύτικο, περιγράφει μόνο τα πρώτα που θα λάβει υποχρεωτικά. εσωτερικά μπορεί να λάβει και άλλα! Μόνο που θα υπάρχει θέμα να δεν σηκώσουμε αυτά που βάζουμε επιπλέον. Για το λόγο αυτό στις ρουτίνες χρησιμοποιούμε για εισαγωγή ότι προκαθορίζουμε, και επίσης προσέχουμε στα τμήματα να βάζουμε ότι χρειάζονται. Με την Σωρός Νέος { } φτιάχνουμε μπλοκ με νέο σωρό. Ο παλιός μπαίνει σε αναμονή και ο νέος διαγράφεται στο πέρας. Υπάρχουν εντολές μετακίνησης στοιχείων (είναι σαν collection αλλά μπορεί να σηκωθεί στοιχείο μόνο από την κορυφή, ενώ μπορούμε να διαβάζουμε άμεσα από οπουδήποτε αν είναι αριθμός ή αλφαριθμητικό, ενώ αντικείμενο πρέπει να το σηκώσουμε από την κορυφή)