Ροή ελέγχου · Κλάσεις και αντικειμενοστρέφεια

method#

Δηλώνει μια ονομασμένη μέθοδο στιγμιότυπου μέσα σε ένα μπλοκ class.

Η method ορίζει υπορουτίνα που αναμένει να κληθεί σε αντικείμενο της περικλείουσας κλάσης. Συμπεριφέρεται σαν sub, με δύο πρόσθετες εγγυήσεις που η sub δεν σας δίνει: το λεξιλογικό $self δένεται αυτόματα στον επικαλούμενο, και οι υπογραφές είναι πάντα ενεργές - γράφετε τις παραμέτρους σαν να ίσχυε use feature 'signatures', και το $self δεν εμφανίζεται σε αυτή την υπογραφή.

Η method είναι έγκυρη μόνο μέσα σε δήλωση class. Εκτός μπλοκ κλάσης αποτελεί σφάλμα κατά τη μεταγλώττιση.

Σημείωση

Πειραματικό χαρακτηριστικό Οι δεσμευμένες λέξεις class, method και field είναι μέρος του πειραματικού χαρακτηριστικού class (εισάχθηκε στην Perl 5.38). Η ενεργοποίησή του με use feature 'class'; εκπέμπει προειδοποίηση στην κατηγορία experimental::class. Η σύνταξη και σημασιολογία ενδέχεται ακόμη να αλλάξουν μεταξύ εκδόσεων της Perl.

Σύνοψη#

method NAME BLOCK
method NAME SIGNATURE BLOCK
method NAME : ATTRS BLOCK
method SIGNATURE BLOCK       # anonymous
method BLOCK                 # anonymous

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

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

Το σώμα μιας method καλείται με το αντικείμενο ως επικαλούμενο. Η τιμή επιστροφής της μεθόδου είναι ό,τι επιστρέφει το μπλοκ, ακολουθώντας τους ίδιους κανόνες περιβάλλοντος με μια κανονική κλήση υπορουτίνας.

Τι σας δίνει η method που δεν σας δίνει η sub#

Τέσσερα πράγματα διαφέρουν από τη γραφή sub μέσα σε μπλοκ class:

  • Το $self είναι προδηλωμένο. Ένα λεξιλογικό $self δημιουργείται στην εμβέλεια της μεθόδου και αρχικοποιείται στον επικαλούμενο. Δεν - και δεν θα έπρεπε να - το αφαιρείτε με shift από το @_.

  • Οι υπογραφές είναι πάντα ενεργές. Μπορείτε να γράψετε method greet($name) { ... } χωρίς use feature 'signatures'. Ο επικαλούμενος $self καταναλώνεται πριν δέσει η υπογραφή, οπότε δεν εμφανίζεται ποτέ στη λίστα παραμέτρων.

  • Τα πεδία είναι σε εμβέλεια. Όλες οι μεταβλητές field που δηλώνονται στην περικλείουσα κλάση είναι ορατές με τα λεξιλογικά τους ονόματα μέσα στο σώμα της μεθόδου. Μια απλή sub μέσα σε μπλοκ class δεν βλέπει πεδία.

  • Καταχωρείται ως μέθοδος. Ο πίνακας μεθόδων της κλάσης καταγράφει το όνομα, το οποίο αναζητά ο μηχανισμός επίλυσης μεθόδων για αποστολή $obj->name(...). Μια απλή sub μέσα στο μπλοκ κλάσης είναι βοηθός, όχι μέθοδος.

Με άλλα λόγια: μια sub μέσα σε μπλοκ class είναι συνηθισμένη υπορουτίνα πακέτου που τυχαίνει να ζει στον χώρο ονομάτων εκείνου του πακέτου. Δεν έχει $self, δεν έχει ορατότητα πεδίων, και δεν αποτελεί μέρος της διεπαφής μεθόδων της κλάσης - καλέστε την μέσω ClassName::helper(...) αν το χρειάζεστε, όχι μέσω βέλους.

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

Μια ελάχιστη κλάση με μέθοδο και πεδίο:

use v5.38;
use feature 'class';
no warnings 'experimental::class';

class Greeter {
    field $greeting = "Hello";

    method greet($name) {
        return "$greeting, $name";
    }
}

my $g = Greeter->new;
say $g->greet("world");           # Hello, world

Οι προεπιλεγμένες τιμές υπογραφής λειτουργούν ακριβώς όπως για την sub:

class Greeter {
    field $greeting = "Hello";

    method greet($name = "someone") {
        return "$greeting, $name";
    }
}

say Greeter->new->greet;          # Hello, someone

Μια μέθοδος χωρίς παραμέτρους εξακολουθεί να χρησιμοποιεί τη μορφή υπογραφής - οι κενές () δεν είναι απαιτητές, αλλά επιτρέπονται και αποτελούν το σύνηθες στιλ όταν η μέθοδος δέχεται ορίσματα αλλού στην κλάση:

class Counter {
    field $n = 0;

    method inc        { $n++ }
    method value ()   { return $n }
}

Μια ανώνυμη μέθοδος - χρήσιμη ως εργοστάσιο ή ως callback που χρειάζεται πρόσβαση στο $self και στα πεδία:

class AnonMethodFactory {
    method make_printer {
        return method { say "called on $self" };
    }
}

Μια λεξιλογική (ιδιωτική) μέθοδος δηλωμένη με my method. Επικαλεστείτε την μέσω του τελεστή ->&, που παρακάμπτει την αναζήτηση μεθόδου και καλεί τη λεξιλογική απευθείας σαν να ήταν μέθοδος:

class LexicalMethod {
    my method _check ($x, $y) {
        return $x > 0 && $y > 0;
    }

    method process ($x, $y) {
        return unless $self->&_check($x, $y);
        # ...
    }
}

Κανονική sub μέσα σε κλάση, σε αντιδιαστολή με method - η sub είναι βοηθός, η method είναι η δημόσια διεπαφή:

class Temperature {
    field $celsius;

    sub _c_to_f ($c) { $c * 9 / 5 + 32 }   # helper, no $self, no fields

    method fahrenheit {
        return _c_to_f($celsius);
    }
}

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

  • Εκτός μπλοκ class είναι σφάλμα κατά τη μεταγλώττιση. Το method foo { ... } στο ανώτατο επίπεδο, ή μέσα σε package που δεν είναι class, δεν αναλύεται. Χρησιμοποιήστε εκεί την sub.

  • Το $self είναι μόνο για ανάγνωση με την έννοια ότι δεν μπορείτε να δηλώσετε άλλο λεξιλογικό με το ίδιο όνομα στην αρχή της μεθόδου - βρίσκεται ήδη σε εμβέλεια. Η εκχώρηση στο $self (π.χ. $self = ...) επιτρέπεται αλλά σπάνια είναι χρήσιμη και δεν αλλάζει τον επικαλούμενο του καλούντος.

  • Το @_ δεν είναι η λίστα ορισμάτων που περιμένετε. Υπό τις υπογραφές που ενεργοποιεί η method, το @_ μέσα στο σώμα είναι κενό μετά τη δέσμευση της υπογραφής, όπως ακριβώς σε κάθε sub που χρησιμοποιεί υπογραφή. Διαβάστε τις παραμέτρους από την υπογραφή, όχι από το @_.

  • Η σειρά επίλυσης μεθόδου ορίζεται από την περικλείουσα κλάση. Η ίδια η method δεν δέχεται επιλογή MRO· η κληρονομικότητα και η αποστολή ακολουθούν ό,τι διαμόρφωσε η δήλωση class μέσω :isa και συναφών γνωρισμάτων.

  • Η method δεν συμμετέχει σε πρωτότυπα. Οι μέθοδοι επικαλούνται μέσω αποστολής, όχι με άμεσες κλήσεις πίνακα συμβόλων, οπότε τα πρωτότυπα (το γνώρισμα :prototype(...) σε μια sub) δεν έχουν εδώ αποτέλεσμα. Χρησιμοποιήστε την υπογραφή για να περιορίσετε το σχήμα κλήσης.

  • Γνωρίσματα. Η μορφή method NAME : ATTRS BLOCK δέχεται γνωρίσματα με τον ίδιο τρόπο όπως η sub NAME : ATTRS BLOCK. Το σύνολο των χρήσιμων γνωρισμάτων στις μεθόδους ακόμη σταθεροποιείται με το χαρακτηριστικό class· συμβουλευτείτε το upstream πριν βασιστείτε σε προσαρμοσμένα.

  • Παγίδα επιστροφής από μέθοδο με ανώνυμη μέθοδο. Το return method { ... } επιστρέφει αναφορά κώδικα. Το method { ... } ως τελευταία έκφραση μεθόδου χωρίς return εξακολουθεί να είναι αναφορά κώδικα, αλλά οι αναγνώστες συχνά την παρερμηνεύουν ως μπλοκ - προτιμήστε ρητή return για σαφήνεια.

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

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

Το χαρακτηριστικό class - και επομένως η method - σημειώνεται πειραματικό στο upstream· η pperl κληρονομεί αυτή την κατάσταση και την κατηγορία προειδοποίησης experimental::class.

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

  • class - δηλώνει το πακέτο μέσα στο οποίο ζει η method· η method αναλύεται μόνο μέσα σε μπλοκ class

  • field - ανά στιγμιότυπο μεταβλητές που είναι ορατές με το όνομά τους μέσα σε κάθε method της περικλείουσας κλάσης

  • sub - δηλώστε κανονική υπορουτίνα· χρησιμοποιήστε αυτό για βοηθούς μέσα σε κλάση που δεν χρειάζονται $self ή πρόσβαση σε πεδία

  • __CLASS__ - το όνομα της τρέχουσας κλάσης, χρήσιμο μέσα σε μεθόδους που χρειάζεται να αποστείλουν πίσω σε κώδικα επιπέδου κλάσης

  • return - ρητή επιστροφή από σώμα μεθόδου· συνιστάται όταν η τελευταία έκφραση είναι η ίδια ανώνυμη μορφή method { ... }

  • my - προθέστε my σε μια method για να δηλώσετε λεξιλογική (ιδιωτική) μέθοδο που επικαλείται μέσω ->&