Κλάσεις και αντικειμενοστρέφεια
CLASS#
Επιστρέφει το όνομα της κλάσης του στιγμιότυπου που χειρίζεται τη δεδομένη στιγμή.
Το __CLASS__ είναι ένα διακριτικό που αναγνωρίζεται κατά τη μεταγλώττιση και αποτιμάται σε χρόνο εκτέλεσης στο όνομα της κλάσης του στιγμιότυπου που το επικαλείται. Μέσα σε σώμα method ή σε έκφραση αρχικοποιητή field (που εισάγεται με use feature 'class'), δίνει την πραγματική κλάση του αντικειμένου που κατασκευάζεται ή χρησιμοποιείται - η οποία μπορεί να είναι υποκλάση του πακέτου στο οποίο βρίσκεται κειμενικά ο κώδικας. Εκτός κώδικα που χρησιμοποιεί το χαρακτηριστικό class, είναι κατ” ουσίαν ισοδύναμο με το ref($self), όμως σε αντίθεση με το ref μπορεί να χρησιμοποιηθεί σε αρχικοποιητή πεδίου, όπου το $self δεν έχει ακόμη δεσμευτεί.
Σύνοψη#
use feature 'class';
field $x = __CLASS__->DEFAULT_X; # in a field initializer
method m { return __CLASS__; } # in a method body
Τι επιστρέφεται#
Μια απλή συμβολοσειρά: το όνομα της κλάσης του στιγμιότυπου που την επικαλείται. Η τιμή είναι το ίδιο είδος συμβολοσειράς που επιστρέφει η ref για μια blessed αναφορά. Δεν είναι αναφορά· καλέστε μεθόδους πάνω της όπως θα κάνατε για οποιοδήποτε όνομα κλάσης.
my $name = __CLASS__; # e.g. "DifferentCustomField"
my $obj = __CLASS__->new(...); # class-method dispatch
Πότε διαφέρει από το __PACKAGE__#
Το __PACKAGE__ επιλύεται κατά τη μεταγλώττιση και ονοματίζει το πακέτο στο οποίο εμφανίζεται κειμενικά το διακριτικό. Το __CLASS__ επιλύεται σε χρόνο εκτέλεσης και ονοματίζει την κλάση του στιγμιότυπου - η οποία, για μέθοδο ή αρχικοποιητή πεδίου που κληρονομείται από υποκλάση, είναι η υποκλάση.
use feature 'class';
class Base {
field $f = __CLASS__->default_f; # evaluated per instance
sub default_f { 10 }
method class_name { __CLASS__ }
method pkg_name { __PACKAGE__ }
}
class Derived :isa(Base) {
sub default_f { 20 }
}
my $obj = Derived->new;
$obj->class_name; # "Derived"
$obj->pkg_name; # "Base"
# $f was initialised to 20, not 10, because __CLASS__ dispatched
# through the Derived package.
Σε μη κληρονομικό περιβάλλον (χωρίς υποκλάσεις), τα __CLASS__ και __PACKAGE__ αποδίδουν την ίδια συμβολοσειρά.
Παραδείγματα#
Μέθοδος κλάσης που καλείται από αρχικοποιητή πεδίου - η κανονική περίπτωση χρήσης. Χωρίς το __CLASS__, μια υποκλάση δεν μπορεί να υπερκαλύψει την προεπιλογή:
use feature 'class';
class WithCustomField {
use constant DEFAULT_X => 10;
field $x = __CLASS__->DEFAULT_X;
}
class DifferentCustomField :isa(WithCustomField) {
sub DEFAULT_X { rand > 0.5 ? 20 : 30 }
}
my $obj = DifferentCustomField->new; # $x is 20 or 30, not 10
Μέσα σε σώμα μεθόδου, ισοδύναμο με ref $self:
class Logger {
method log ($msg) {
print STDERR "[", __CLASS__, "] $msg\n";
}
}
Κατασκευή νέου στιγμιότυπου της ίδιας κλάσης με το αντικείμενο που το επικαλείται - χρήσιμο για εργοστασιακές μεθόδους τύπου clone που πρέπει να σέβονται τις υποκλάσεις:
class Node {
field $label :param;
method spawn ($child_label) {
return __CLASS__->new(label => $child_label);
}
}
Σύγκριση με το __PACKAGE__ για διαγνωστικά που θέλουν να καρφώσουν τον ακριβή στόχο αποστολής:
class Thing {
method describe {
return sprintf "defined in %s, dispatched as %s",
__PACKAGE__, __CLASS__;
}
}
Οριακές περιπτώσεις#
Έγκυρο μόνο υπό
use feature 'class'μέσα σε σώμαmethod, σε αρχικοποιητήfield, ή σε άλλη κατασκευή του χαρακτηριστικού class (για παράδειγμα μπλοκADJUST). Η χρήση του εκτός τέτοιου περιβάλλοντος είναι σφάλμα κατά τη μεταγλώττιση.Χωρίς παρενθέσεις, χωρίς ορίσματα. Το
__CLASS__είναι διακριτικό τύπου bareword, όχι κλήση συνάρτησης. Το__CLASS__()είναι συντακτικό σφάλμα.Δεν είναι το ίδιο με
ref $selfκατά την αρχικοποίηση των πεδίων - το$selfδεν έχει ακόμη δεσμευτεί όσο τα πεδία ορίζονται, άρα τοref $selfδεν είναι διαθέσιμο. Το__CLASS__είναι ο μόνος τρόπος να φτάσετε στην κλάση του στιγμιότυπου μέσα από αρχικοποιητή πεδίου.Δεν είναι
refγια κλήση μεθόδου κλάσης. Όταν καλείται ως μέθοδος κλάσης (χωρίς στιγμιότυπο στο χέρι), το__CLASS__αποδίδει την κλάση πάνω στην οποία κλήθηκε η μέθοδος, όχι το πακέτο στο οποίο ορίστηκε η μέθοδος. Αυτό αντικατοπτρίζει την κανονική αποστολή μεθόδου.Συμβολοσειρά, όχι αναφορά. Οι κλήσεις μεθόδων μέσω
__CLASS__->...είναι αποστολές μεθόδων κλάσης, όχι αποστολές μεθόδων στιγμιότυπου. Η μέθοδος δεν θα δει blessed αναφορά ως invocant.Το χαρακτηριστικό
classείναι σημειωμένο ως πειραματικό στην Perl 5.42· εκπέμπει προειδοποίησηexperimental::classεκτός αν σιγηθεί μεno warnings 'experimental::class'.
Διαφορές από το upstream#
Πλήρως συμβατό με το upstream Perl 5.42.
Δείτε επίσης#
__PACKAGE__- όνομα πακέτου κατά τη μεταγλώττιση του περιβάλλοντος κώδικα· χρησιμοποιήστε το όταν θέλετε το κειμενικό πακέτο, όχι την κλάση χρόνου εκτέλεσηςref- όνομα κλάσης χρόνου εκτέλεσης μιας blessed αναφοράς· χρησιμοποιήστε το όταν κρατάτε ήδη στιγμιότυπο και δεν βρίσκεστε μέσα σε αρχικοποιητή πεδίουbless- συσχετίζει μια αναφορά με όνομα κλάσης· η χαμηλού επιπέδου πρωτογενής λειτουργία στην οποία τελικά επιλύεται η αποστολή τύπου__CLASS__isa- ελέγχει αν η τρέχουσα κλάση είναι υποκλάση ενός δοθέντος ονόματος· συνδυάζεται φυσικά με το__CLASS__για ελέγχους χρόνου εκτέλεσηςsub- δηλώνει υπορουτίνες, συμπεριλαμβανομένης της μορφήςmethodπου κάνει το__CLASS__να έχει νόημα