Κλάσεις και αντικειμενοστρέφεια

ref#

Επιστρέφει μια συμβολοσειρά που περιγράφει σε τι δείχνει μια αναφορά.

Η ref εξετάζει τον τελεστέο της και επιστρέφει μια συμβολοσειρά που προσδιορίζει το είδος του αναφερόμενου. Για blessed αναφορά επιστρέφει το όνομα της κλάσης· για μη-blessed αναφορά επιστρέφει μία από τις ενσωματωμένες συμβολοσειρές τύπου (SCALAR, ARRAY, HASH, CODE, GLOB, LVALUE, IO, FORMAT, REF, VSTRING, REGEXP). Για οτιδήποτε δεν είναι αναφορά επιστρέφει την κενή συμβολοσειρά. Χωρίς όρισμα, η ref λειτουργεί επί της $_.

Σύνοψη#

ref EXPR
ref

Τι επιστρέφεται#

Μια συμβολοσειρά. Τρεις αμοιβαία αποκλειόμενες κατηγορίες:

  • Blessed αναφορά - το όνομα της κλάσης στην οποία έχει γίνει bless ο αναφερόμενος. Για παράδειγμα, μια αναφορά bless {}, 'Dog' επιστρέφει "Dog". Οι υποκλάσεις επιστρέφουν το δικό τους όνομα, όχι του γονέα: μια αναφορά που έγινε bless στην Puppy (η οποία είναι ISA της Dog) επιστρέφει "Puppy". Δείτε bless.

  • Μη-blessed αναφορά - μία από τις ενσωματωμένες συμβολοσειρές τύπου που παρατίθενται παρακάτω, που προσδιορίζει τον φυσικό τύπο του αναφερόμενου.

  • Μη-αναφορά - η κενή συμβολοσειρά "".

Η κενή συμβολοσειρά είναι η μοναδική ψευδής τιμή που επιστρέφει ποτέ η ref, οπότε το if (ref $x) είναι ασφαλής έλεγχος «είναι αυτό αναφορά;». Δείτε την ενότητα οριακών περιπτώσεων για ποιον λόγο το if (ref $x eq 'HASH') δεν είναι ασφαλής έλεγχος «είναι αυτό αναφορά hash;».

Ενσωματωμένες συμβολοσειρές τύπου#

Επιστρέφονται για μη-blessed αναφορές σύμφωνα με τον φυσικό αναφερόμενο:

Συμβολοσειρά

Αναφερόμενος

SCALAR

αναφορά σε κανονικό βαθμωτό

ARRAY

αναφορά σε πίνακα

HASH

αναφορά σε hash

CODE

αναφορά σε υπορουτίνα

GLOB

αναφορά σε typeglob

LVALUE

αναφορά σε εκχωρήσιμη έκφραση

IO

αναφορά σε handle I/O

FORMAT

αναφορά σε format

REF

αναφορά σε άλλη αναφορά

VSTRING

αναφορά σε βαθμωτό τύπου v-string

REGEXP

αναφορά σε ωμό (μη-blessed) regexp

Ένα μεταγλωττισμένο regex από qr// είναι blessed στην κλάση Regexp κατά τη δημιουργία, οπότε η ref qr/.../ συνήθως επιστρέφει "Regexp", όχι "REGEXP". Η σκέτη συμβολοσειρά REGEXP εμφανίζεται μόνο για μη-blessed regex αναφερόμενους, που είναι σπάνιοι έξω από τα εσωτερικά.

Παραδείγματα#

Βασικές δοκιμές τύπου:

ref \1              # "SCALAR"
ref []              # "ARRAY"
ref {}              # "HASH"
ref sub { }         # "CODE"
ref \*STDOUT        # "GLOB"
ref \\1             # "REF"    (reference to a reference)
ref qr/foo/         # "Regexp" (blessed)
ref "plain string"  # ""       (not a reference)
ref 42              # ""
ref undef           # ""

Οι blessed αναφορές επιστρέφουν το όνομα της κλάσης:

my $obj = bless {}, 'My::Widget';
ref $obj;                       # "My::Widget"

Προστατευτείτε πριν την αποαναφορά:

sub stringify {
    my ($v) = @_;
    return "[undef]"           if !defined $v;
    return "[ref: " . ref($v) . "]" if ref $v;
    return $v;
}

Η μορφή χωρίς όρισμα διαβάζει την $_:

for my $item (@things) {
    print "skipping non-ref\n" and next unless ref;
    ...
}

Επιλέγοντας τον σωστό έλεγχο#

Η ref είναι το παλαιότερο πρωτογενές στοιχείο εσωτερικής σκόπευσης της γλώσσας και συνδυάζει τρεις διαφορετικές ερωτήσεις. Ο σύγχρονος κώδικας πρέπει να επιλέγει τον τελεστή που ταιριάζει με την ερώτηση που τίθεται.

Είναι αυτό καθόλου αναφορά;

if (ref $x) { ... }             # empty string is the only false return

Είναι αυτό αντικείμενο μιας δεδομένης κλάσης (ή παραγόμενο από αυτήν); Χρησιμοποιήστε τον τελεστή isa (ή τη μέθοδο UNIVERSAL::isa) - διατρέχει το @ISA και τιμά την υποκλασιοποίηση, κάτι που μια κυριολεκτική σύγκριση με ref δεν κάνει:

if ($obj isa 'My::Widget') { ... }      # true for subclasses too
if ($obj->isa('My::Widget')) { ... }    # method form

if (ref($obj) eq 'My::Widget') { ... }  # FRAGILE: fails for subclasses

Ποιος είναι ο υποκείμενος φυσικός τύπος, ανεξάρτητα από το blessing; Χρησιμοποιήστε την Scalar::Util::reftype - αγνοεί την κλάση και επιστρέφει την ενσωματωμένη συμβολοσειρά τύπου ακόμη και για blessed αναφορές:

use Scalar::Util qw(reftype blessed);
reftype($obj);                  # "HASH" if $obj is blessed hash ref
blessed($obj);                  # class name, or undef if not blessed

Οριακές περιπτώσεις#

  • Ποτέ μη χρησιμοποιείτε τη ref ως τιμή αλήθειας του αναφερόμενου. Μια αναφορά που έγινε bless σε κλάση με κυριολεκτικό όνομα 0 κάνει την ref $obj να επιστρέφει τη συμβολοσειρά "0", που είναι ψευδής. Είναι σπάνιο εκ κατασκευής, αλλά η παγίδα είναι παλιά και γνωστή. Συγκρίνετε με την κενή συμβολοσειρά στη θέση της: if (ref $x ne "").

  • Συγκρούσεις ονομάτων κλάσεων με ενσωματωμένες συμβολοσειρές τύπου. Τίποτα δεν σας εμποδίζει να γράψετε package HASH; sub new { bless {}, shift }. Τότε η ref(HASH->new) επιστρέφει "HASH" - διακρίνεται από μη-blessed αναφορά hash μόνο με τη ref. Χρησιμοποιήστε την Scalar::Util::blessed για αποσαφήνιση, ή την reftype για να θέσετε άμεσα την ερώτηση φυσικού τύπου.

  • Η ref σε qr// επιστρέφει "Regexp", όχι "REGEXP". Τα αντικείμενα qr// είναι blessed κατά την κατασκευή· η κεφαλαία μορφή παράγεται μόνο για την (ασυνήθιστη) μη-blessed αναφορά regex.

  • Μεταβλητές με tie: η ref βλέπει μέσα από το tie στην υποκείμενη αναφορά. Χρησιμοποιήστε την tied για να ανακτήσετε το αντικείμενο που υποστηρίζει το tie.

  • Οι ασθενείς αναφορές εξακολουθούν να είναι αναφορές: η ref συμπεριφέρεται ταυτόσημα για ασθενείς και ισχυρές αναφορές. Χρησιμοποιήστε την Scalar::Util::isweak για να ανιχνεύσετε την ασθένεια.

  • Η υπερφορτωμένη μετατροπή σε συμβολοσειρά δεν επηρεάζει τη ref. Η τιμή επιστροφής της ref παράγεται από το runtime, όχι από την υπερφόρτωση "" του αντικειμένου.

  • Η ref EXPR έχει πολύ υψηλή προτεραιότητα - αναλύεται ως ονομασμένος μοναδιαίος τελεστής. Βάλτε παρενθέσεις όταν το όρισμα είναι οτιδήποτε πιο σύνθετο από μια απλή μεταβλητή:

    ref $a || $b;         # parsed as (ref $a) || $b
    ref($a || $b);        # what you probably meant
    

Διαφορές από το upstream#

Πλήρως συμβατό με το upstream Perl 5.42.

Δείτε επίσης#

  • bless - εγκαθιστά ένα όνομα κλάσης σε μια αναφορά· το όνομα που εγκαθίσταται εδώ είναι ακριβώς αυτό που επιστρέφει στη συνέχεια η ref

  • isa - έλεγχος συμμετοχής σε κλάση που τιμά την κληρονομικότητα του @ISA· προτιμήστε την έναντι του ref(...) eq 'ClassName' για αντικειμενοστρεφή διανομή

  • tied - ανακτά το αντικείμενο που υλοποιεί μια μεταβλητή με tie· η ref σε ένα βαθμωτό με tie ακολουθεί το tie μέχρι τον αναφερόμενο

  • Scalar::Util::reftype - συμβολοσειρά φυσικού τύπου για αναφορά, αγνοώντας το blessing

  • Scalar::Util::blessed - όνομα κλάσης αν είναι blessed, undef διαφορετικά· το μονοσήμαντο αντίστοιχο της ref για αντικειμενοστρεφή κώδικα

  • perlref, perlobj - εγχειρίδια αναφοράς για αναφορές και μοντέλο αντικειμένων