Εμβέλεια · Κλάσεις και αντικειμενοστρέφεια
class#
Δηλώνει έναν χώρο ονομάτων που συμπεριφέρεται ως εγγενής κλάση αντικειμένων.
Η class εισάγει ένα νέο πακέτο όπως ακριβώς και η package, αλλά το χαρακτηρίζει ως κλάση: ο runtime προσαρτά έναν κατασκευαστή με το όνομα new, ενεργοποιεί τις δεσμευμένες λέξεις field και method μέσα στο σώμα της, και υποστηρίζει απλή κληρονομικότητα μέσω του χαρακτηριστικού :isa. Είναι η απάντηση του πυρήνα της γλώσσας στον χειροποίητο αντικειμενοστρεφή προγραμματισμό βασισμένο στο bless - το ίδιο πρόβλημα, χωρίς το επαναλαμβανόμενο πλαίσιο κώδικα.
Σημείωση
Πειραματικό Το χαρακτηριστικό class (κωδική ονομασία Corinna) είναι πειραματικό στην Perl 5.42 και μπορεί να αλλάξει με μη συμβατούς τρόπους. Ενεργοποιήστε το με use feature 'class' και αποσιωπήστε την ειδοποίηση με no warnings 'experimental::class'.
Σύνοψη#
class NAMESPACE; # rest-of-scope form
class NAMESPACE VERSION;
class NAMESPACE :ATTRIBUTES;
class NAMESPACE BLOCK # block form
class NAMESPACE VERSION BLOCK
class NAMESPACE VERSION :ATTRIBUTES BLOCK
Ελάχιστη λειτουργική κλάση:
use v5.38;
use feature 'class';
no warnings 'experimental::class';
class Point {
field $x :param;
field $y :param;
method distance_from_origin {
return sqrt($x ** 2 + $y ** 2);
}
}
my $p = Point->new(x => 3, y => 4);
say $p->distance_from_origin; # 5
Τι επιστρέφεται#
Η class είναι δήλωση, όχι έκφραση - δεν επιστρέφει τιμή που μπορείτε να αναθέσετε. Αυτό που λαμβάνετε είναι:
Ένα νέο πακέτο στον πίνακα συμβόλων, προσπελάσιμο όπως οποιοδήποτε άλλο πακέτο.
Έναν παραγόμενο κατασκευαστή
new. Μην γράφετε δικό σαςnew. Ο παραγόμενος τιμά τα χαρακτηριστικά πεδίων:paramκαι εκτελεί κάθε μπλοκADJUSTμε τη σειρά δήλωσης.Το
$selfδεσμεύεται έμμεσα μέσα σε κάθε σώμαmethod.Το
__CLASS__είναι χρησιμοποιήσιμο μέσα σε αρχικοποιητές πεδίων και μεθόδους για να ονομάσει την κλάση που κατασκευάζεται τη δεδομένη στιγμή (η οποία μπορεί να είναι υποκλάση).
Μορφές#
Η class δέχεται τέσσερις συντακτικές μορφές. Ο διαχωρισμός μεταξύ των μορφών μπλοκ και δήλωσης αντικατοπτρίζει ακριβώς την package:
class NAME BLOCK- ο ορισμός της κλάσης είναι το περιεχόμενο του μπλοκ. Η εμβέλεια τερματίζει με το άγκιστρο κλεισίματος.class NAME;- η υπόλοιπη τρέχουσα εμβέλεια (ή αρχείο) μέχρι την επόμενη δήλωσηclassήpackageαποτελεί το σώμα της κλάσης. Χρήσιμο για αρχεία μίας κλάσης.class NAME VERSION ...- η έκδοση δηλώνεται όπως στοpackage Foo 1.234. Η έκδοση πρέπει να προηγείται οποιωνδήποτε χαρακτηριστικών.class NAME :ATTRIBUTES ...- ένα ή περισσότερα χαρακτηριστικά κλάσης, χωρισμένα με λευκούς χαρακτήρες, καθένα ξεκινώντας με:. Το μόνο χαρακτηριστικό κλάσης που ορίζεται προς το παρόν είναι το:isa.
class My::Thing 1.02 :isa(My::Base) {
# body
}
Πεδία, μέθοδοι, ADJUST#
Μέσα στο σώμα μιας κλάσης τρεις νέες δεσμευμένες λέξεις βρίσκονται εντός εμβέλειας:
Η
fieldδηλώνει αποθηκευτικό χώρο ανά στιγμιότυπο. Τα πεδία συμπεριφέρονται σαν λεξιλογικές μεταβλητές μέσα στις μεθόδους, αλλά κάθε στιγμιότυπο έχει τη δική του θέση. Τα χαρακτηριστικά:param,:readerκαι:writerπαράγουν σύνδεση κατασκευαστή και προσπελαστές.Η
methodδηλώνει μια υπορουτίνα που δεσμεύει αυτόματα το$selfκαι που μπορεί να διαβάζει και να γράφει τα περικλείοντα πεδία με το όνομά τους. Οι μέθοδοι λειτουργούν σαν να ίσχυε τοuse feature 'signatures'· το$selfδεν εμφανίζεται στην υπογραφή.Το
ADJUST BLOCKεκτελείται μετά τους αρχικοποιητές πεδίων, κατά την κατασκευή, με το$selfήδη δεσμευμένο. Χρησιμοποιήστε το για επικύρωση μετά την κατασκευή και για παράγωγα πεδία.
class Counter {
field $value :param = 0;
field $step :param = 1;
ADJUST {
die "step must be positive" if $step <= 0;
}
method tick { $value += $step }
method peek { $value }
}
Τα πεδία είναι πάντα λεξιλογικά ως προς την κλάση - δεν κληρονομούνται. Οι υποκλάσεις που χρειάζονται πρόσβαση στην κατάσταση μιας γονικής κλάσης την αποκτούν μέσω μεθόδων, όχι μέσω πεδίων.
Κληρονομικότητα: :isa#
Μια κλάση κληρονομεί από το πολύ μία άλλη κλάση:
class Shape { ... }
class Circle :isa(Shape) {
field $r :param;
method area { 3.14159265 * $r * $r }
}
Υποστηρίζεται μόνο απλή κληρονομικότητα. Ο στόχος του :isa φορτώνεται αυτόματα αν δεν βρίσκεται ήδη στη μνήμη - ισοδύναμο με use MODULE () πριν από τη δήλωση της κλάσης. Μπορεί να απαιτηθεί ελάχιστη έκδοση με τον ίδιο τρόπο όπως το use MODULE VERSION:
class Circle :isa(Shape 2.000) { ... }
Το :isa κληρονομεί μόνο μεθόδους. Τα πεδία είναι ιδιωτικός αποθηκευτικός χώρος ανά κλάση· μια υποκλάση δεν έχει έμμεση όψη στα πεδία της γονικής κλάσης.
Καθολική κατάσταση που επηρεάζει#
%INC- το:isa(Parent)φορτώνει τοParentμέσωrequireκατά την πρώτη χρήση και το καταγράφει εδώ, ακριβώς όπως τοuse.@ISA- συμπληρώνεται για την κλάση από το χαρακτηριστικό:isa, ώστε η υπάρχουσα ενδοσκόπησηisa/UNIVERSAL/SUPER::να εξακολουθεί να λειτουργεί.Ο πίνακας συμβόλων - το όνομα της κλάσης γίνεται stash στο
%::ακριβώς όπως θα δημιουργούσε ηpackage.
Παραδείγματα#
Απλή κλάση με μια υποχρεωτική παράμετρο και ένα παράγωγο πεδίο:
class User {
field $name :param;
field $greeting;
ADJUST { $greeting = "Hello, $name" }
method greet { say $greeting }
}
User->new(name => 'Ada')->greet; # Hello, Ada
Προεπιλεγμένες τιμές παραμέτρων - το = εφαρμόζεται όταν ο καλών παρέλειψε την παράμετρο· το //= εφαρμόζεται επίσης όταν η τιμή ήταν undef· το ||= εφαρμόζεται επίσης όταν η τιμή ήταν ψευδής:
class Window {
field $title :param = 'untitled';
field $width :param //= 640;
field $shown :param ||= 1;
}
Απλή κληρονομικότητα με υπερκάλυψη μεθόδου:
class Animal {
field $name :param;
method speak { "some sound" }
method introduce { say $name, " says ", $self->speak }
}
class Dog :isa(Animal) {
method speak { "woof" }
}
Dog->new(name => 'Rex')->introduce; # Rex says woof
Ιδιωτική μέθοδος μέσω λεξιλογικού my method, η οποία καλείται μέσω ->&:
class Safe {
field $secret :param;
my method check ($n) { $n == $secret }
method unlock ($n) {
return $self->&check($n) ? "open" : "denied";
}
}
Χρήση του __CLASS__ ώστε ένας αρχικοποιητής πεδίου της βασικής κλάσης να εντοπίζει την υπερκάλυψη της υποκλάσης:
class Base {
sub DEFAULT_X { 10 }
field $x = __CLASS__->DEFAULT_X;
method x { $x }
}
class Tuned :isa(Base) {
sub DEFAULT_X { 99 }
}
say Tuned->new->x; # 99
Μορφή δήλωσης για το υπόλοιπο του αρχείου:
use v5.38;
use feature 'class';
class Config;
field $path :param;
method path { $path }
# File ends here; whole remainder is Config's body.
Οριακές περιπτώσεις#
Μην ορίζετε
new. Ο παραγόμενος κατασκευαστής είναι το μόνο υποστηριζόμενο σημείο εισόδου. Έναsub new { ... }γραμμένο από τον χρήστη μέσα σε σώμαclassαποτελεί σφάλμα κατά τη μεταγλώττιση.Καμία πολλαπλή κληρονομικότητα. Το
:isa(A, B)είναι συντακτικό σφάλμα. Πολλαπλά χαρακτηριστικά:isaσε μία κλάση επίσης απορρίπτονται.Καμία τροποποίηση του
@ISA. Αντιμετωπίστε το@ISAως μόνο για ανάγνωση για κλάσεις που δηλώνονται μεclass. Η προσθήκη σε αυτό κατά τον χρόνο εκτέλεσης είναι απροσδιόριστη.Η
packageδεν μπορεί να ξανανοίξει μια κλάση. Μόλις ένας χώρος ονομάτων δηλωθεί μεclass, οι επόμενες δηλώσειςpackageπου στοχεύουν το ίδιο όνομα αποτελούν σφάλμα κατά τη μεταγλώττιση, και αντιστρόφως.Τα πεδία δεν είναι λεξιλογικές μεταβλητές με τη συνηθισμένη έννοια. Δεν μπορείτε να αναφερθείτε σε ένα πεδίο από έξω από το σώμα της κλάσης, και δεν μπορείτε να εφαρμόσετε
ourήlocalσε αυτό. Μόνο μέθοδοι και μπλοκADJUSTβλέπουν τα πεδία.Το
$selfείναι μόνο για ανάγνωση μέσα σε μια μέθοδο. Η ανάθεση σε αυτό αποτελεί σφάλμα κατά τον χρόνο εκτέλεσης.Οι αρχικοποιητές πεδίων εκτελούνται πριν υπάρξει το
$self. Μέσα σεfield $x = EXPR, μπορείτε να χρησιμοποιήσετε__CLASS__και προηγουμένως δηλωμένα πεδία, αλλά όχι το$self. Οτιδήποτε χρειάζεται το πλήρως κατασκευασμένο στιγμιότυπο ανήκει σε μπλοκADJUST.Καμία πρόσβαση σε πεδίο πριν τη δήλωση. Μέσα στην έκφραση αρχικοποιητή ενός πεδίου, ορατά είναι μόνο τα πεδία που έχουν δηλωθεί νωρίτερα στο σώμα της κλάσης.
Επίλυση μεθόδων. Η αποστολή εξακολουθεί να γίνεται μέσω της συνήθους MRO (
UNIVERSAL::isa,SUPER::), οπότε το$self->SUPER::foo(@args)λειτουργεί όπως και για κλάσεις βασισμένες στοbless.Εμβέλεια μορφής δήλωσης. Η
class Foo;καταναλώνει το υπόλοιπο του περικλείοντος μπλοκ - συνήθως το υπόλοιπο του αρχείου. Μια δεύτερηclassήpackageτην τερματίζει· δεν υπάρχει τρόπος να «κλείσει» πρόωρα μια κλάση μορφής δήλωσης.Πειραματική προειδοποίηση. Κάθε δήλωση
classεκπέμπει μια προειδοποίησηclass is experimentalυπό τις προεπιλεγμένες προειδοποιήσεις. Χρησιμοποιήστεno warnings 'experimental::class'μόλις το χαρακτηριστικό μπει σε πραγματική χρήση.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42. Το χαρακτηριστικό επισημαίνεται ως πειραματικό στο upstream· η pperl αντικατοπτρίζει αυτή την κατάσταση και εκπέμπει την ίδια κατηγορία προειδοποίησης (experimental::class).
Δείτε επίσης#
field- δηλώνει αποθηκευτικό χώρο ανά στιγμιότυπο μέσα σε σώμαclass· υποστηρίζει τα:param,:reader,:writermethod- δηλώνει μια υπορουτίνα με έμμεσο$selfκαι άμεση πρόσβαση στα πεδία της περικλείουσας κλάσηςpackage- η δήλωση χώρου ονομάτων χωρίς κλάση· ηclassείναι το αντικειμενοστρεφές αδελφικό αντίστοιχο με τις ίδιες συντακτικές μορφέςbless- ο πριν την 5.38 τρόπος σύνδεσης μιας κλάσης σε μια αναφορά· εξακολουθεί να υποστηρίζεται και διαλειτουργεί με αντικείμενα κατασκευασμένα μεclassγια ελέγχουςisa/canisa- τελεστής για έλεγχο μέλους κλάσης· λειτουργεί τόσο για αντικείμενα δηλωμένα μεclassόσο και για βασισμένα στοblessuse- πώς το:isa(Parent)φορτώνει τη γονική κλάση από κάτω από τα παρασκήνια