⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 perltoot.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 5 页
字号:
multiple versions of a module.  Lamentably..Sh "Deeper \s-1UNIVERSAL\s0 details".IX Subsection "Deeper UNIVERSAL details"It is also valid (though perhaps unwise in most cases) to put otherpackages' names in \f(CW@UNIVERSAL::ISA\fR.  These packages will also beimplicitly inherited by all classes, just as \s-1UNIVERSAL\s0 itself is.However, neither \s-1UNIVERSAL\s0 nor any of its parents from the \f(CW@ISA\fR treeare explicit base classes of all objects.  To clarify, given thefollowing:.PP.Vb 1\&    @UNIVERSAL::ISA = (\*(AqREALLYUNIVERSAL\*(Aq);\&\&    package REALLYUNIVERSAL;\&    sub special_method { return "123" }\&\&    package Foo;\&    sub normal_method { return "321" }.Ve.PPCalling Foo\->\fIspecial_method()\fR will return \*(L"123\*(R", but callingFoo\->isa('\s-1REALLYUNIVERSAL\s0') or Foo\->isa('\s-1UNIVERSAL\s0') will returnfalse..PPIf your class is using an alternate mro like C3 (seemro), method resolution within \s-1UNIVERSAL\s0 / \f(CW@UNIVERSAL::ISA\fR willstill occur in the default depth-first left-to-right manner,after the class's C3 mro is exhausted..PPAll of the above is made more intuitive by realizing what reallyhappens during method lookup, which is roughly like thisugly pseudo-code:.PP.Vb 11\&    get_mro(class) {\&        # recurses down the @ISA\*(Aqs starting at class,\&        # builds a single linear array of all\&        # classes to search in the appropriate order.\&        # The method resolution order (mro) to use\&        # for the ordering is whichever mro "class"\&        # has set on it (either default (depth first\&        # l\-to\-r) or C3 ordering).\&        # The first entry in the list is the class\&        # itself.\&    }\&\&    find_method(class, methname) {\&        foreach $class (get_mro(class)) {\&            if($class\->has_method(methname)) {\&                return ref_to($class\->$methname);\&            }\&        }\&        foreach $class (get_mro(UNIVERSAL)) {\&            if($class\->has_method(methname)) {\&                return ref_to($class\->$methname);\&            }\&        }\&        return undef;\&    }.Ve.PPHowever the code that implements UNIVERSAL::isa does notsearch in \s-1UNIVERSAL\s0 itself, only in the package's actual\&\f(CW@ISA\fR..SH "Alternate Object Representations".IX Header "Alternate Object Representations"Nothing requires objects to be implemented as hash references.  An objectcan be any sort of reference so long as its referent has been suitablyblessed.  That means scalar, array, and code references are also fairgame..PPA scalar would work if the object has only one datum to hold.  An arraywould work for most cases, but makes inheritance a bit dodgy becauseyou have to invent new indices for the derived classes..Sh "Arrays as Objects".IX Subsection "Arrays as Objects"If the user of your class honors the contract and sticks to the advertisedinterface, then you can change its underlying interface if you feellike it.  Here's another implementation that conforms to the sameinterface specification.  This time we'll use an array referenceinstead of a hash reference to represent the object..PP.Vb 2\&    package Person;\&    use strict;\&\&    my($NAME, $AGE, $PEERS) = ( 0 .. 2 );\&\&    ############################################\&    ## the object constructor (array version) ##\&    ############################################\&    sub new {\&        my $self = [];\&        $self\->[$NAME]   = undef;  # this is unnecessary\&        $self\->[$AGE]    = undef;  # as is this\&        $self\->[$PEERS]  = [];     # but this isn\*(Aqt, really\&        bless($self);\&        return $self;\&    }\&\&    sub name {\&        my $self = shift;\&        if (@_) { $self\->[$NAME] = shift }\&        return $self\->[$NAME];\&    }\&\&    sub age {\&        my $self = shift;\&        if (@_) { $self\->[$AGE] = shift }\&        return $self\->[$AGE];\&    }\&\&    sub peers {\&        my $self = shift;\&        if (@_) { @{ $self\->[$PEERS] } = @_ }\&        return @{ $self\->[$PEERS] };\&    }\&\&    1;  # so the require or use succeeds.Ve.PPYou might guess that the array access would be a lot faster than thehash access, but they're actually comparable.  The array is a \fIlittle\fRbit faster, but not more than ten or fifteen percent, even when youreplace the variables above like \f(CW$AGE\fR with literal numbers, like 1.A bigger difference between the two approaches can be found in memory use.A hash representation takes up more memory than an array representationbecause you have to allocate memory for the keys as well as for the values.However, it really isn't that bad, especially since as of version 5.004,memory is only allocated once for a given hash key, no matter how manyhashes have that key.  It's expected that sometime in the future, eventhese differences will fade into obscurity as more efficient underlyingrepresentations are devised..PPStill, the tiny edge in speed (and somewhat larger one in memory)is enough to make some programmers choose an array representationfor simple classes.  There's still a little problem withscalability, though, because later in life when you feellike creating subclasses, you'll find that hashes just workout better..Sh "Closures as Objects".IX Subsection "Closures as Objects"Using a code reference to represent an object offers some fascinatingpossibilities.  We can create a new anonymous function (closure) whoalone in all the world can see the object's data.  This is because weput the data into an anonymous hash that's lexically visible only tothe closure we create, bless, and return as the object.  This object'smethods turn around and call the closure as a regular subroutine call,passing it the field we want to affect.  (Yes,the double-function call is slow, but if you wanted fast, you wouldn'tbe using objects at all, eh? :\-).PPUse would be similar to before:.PP.Vb 7\&    use Person;\&    $him = Person\->new();\&    $him\->name("Jason");\&    $him\->age(23);\&    $him\->peers( [ "Norbert", "Rhys", "Phineas" ] );\&    printf "%s is %d years old.\en", $him\->name, $him\->age;\&    print "His peers are: ", join(", ", @{$him\->peers}), "\en";.Ve.PPbut the implementation would be radically, perhaps even sublimelydifferent:.PP.Vb 1\&    package Person;\&\&    sub new {\&         my $class  = shift;\&         my $self = {\&            NAME  => undef,\&            AGE   => undef,\&            PEERS => [],\&         };\&         my $closure = sub {\&            my $field = shift;\&            if (@_) { $self\->{$field} = shift }\&            return    $self\->{$field};\&        };\&        bless($closure, $class);\&        return $closure;\&    }\&\&    sub name   { &{ $_[0] }("NAME",  @_[ 1 .. $#_ ] ) }\&    sub age    { &{ $_[0] }("AGE",   @_[ 1 .. $#_ ] ) }\&    sub peers  { &{ $_[0] }("PEERS", @_[ 1 .. $#_ ] ) }\&\&    1;.Ve.PPBecause this object is hidden behind a code reference, it's probably a bitmysterious to those whose background is more firmly rooted in standardprocedural or object-based programming languages than in functionalprogramming languages whence closures derive.  The objectcreated and returned by the \fInew()\fR method is itself not a data referenceas we've seen before.  It's an anonymous code reference that has withinit access to a specific version (lexical binding and instantiation)of the object's data, which are stored in the private variable \f(CW$self\fR.Although this is the same function each time, it contains a differentversion of \f(CW$self\fR..PPWhen a method like \f(CW\*(C`$him\->name("Jason")\*(C'\fR is called, its implicitzeroth argument is the invoking object\*(--just as it is with all methodcalls.  But in this case, it's our code reference (something like afunction pointer in \*(C+, but with deep binding of lexical variables).There's not a lot to be done with a code reference beyond calling it, sothat's just what we do when we say \f(CW\*(C`&{$_[0]}\*(C'\fR.  This is just a regularfunction call, not a method call.  The initial argument is the string\&\*(L"\s-1NAME\s0\*(R", and any remaining arguments are whatever had been passed to themethod itself..PPOnce we're executing inside the closure that had been created in \fInew()\fR,the \f(CW$self\fR hash reference suddenly becomes visible.  The closure grabsits first argument (\*(L"\s-1NAME\s0\*(R" in this case because that's what the \fIname()\fRmethod passed it), and uses that string to subscript into the privatehash hidden in its unique version of \f(CW$self\fR..PPNothing under the sun will allow anyone outside the executing method tobe able to get at this hidden data.  Well, nearly nothing.  You \fIcould\fRsingle step through the program using the debugger and find out thepieces while you're in the method, but everyone else is out of luck..PPThere, if that doesn't excite the Scheme folks, then I just don't knowwhat will.  Translation of this technique into \*(C+, Java, or any otherbraindead-static language is left as a futile exercise for aficionadosof those camps..PPYou could even add a bit of nosiness via the \fIcaller()\fR function andmake the closure refuse to operate unless called via its own package.This would no doubt satisfy certain fastidious concerns of programmingpolice and related puritans..PPIf you were wondering when Hubris, the third principle virtue of aprogrammer, would come into play, here you have it. (More seriously,Hubris is just the pride in craftsmanship that comes from having writtena sound bit of well-designed code.).SH "AUTOLOAD: Proxy Methods".IX Header "AUTOLOAD: Proxy Methods"Autoloading is a way to intercept calls to undefined methods.  An autoloadroutine may choose to create a new function on the fly, either loadedfrom disk or perhaps just \fIeval()\fRed right there.  This define-on-the-flystrategy is why it's called autoloading..PPBut that's only one possible approach.  Another one is to justhave the autoloaded method itself directly provide therequested service.  When used in this way, you may thinkof autoloaded methods as \*(L"proxy\*(R" methods..PPWhen Perl tries to call an undefined function in a particular packageand that function is not defined, it looks for a function inthat same package called \s-1AUTOLOAD\s0.  If one exists, it's calledwith the same arguments as the original function would have had.The fully-qualified name of the function is stored in that package'sglobal variable \f(CW$AUTOLOAD\fR.  Once called, the function can do anythingit would like, including defining a new function by the right name, andthen doing a really fancy kind of \f(CW\*(C`goto\*(C'\fR right to it, erasing itselffrom the call stack..PPWhat does this have to do with objects?  After all, we keep talking aboutfunctions, not methods.  Well, since a method is just a function withan extra argument and some fancier semantics about where it's found,we can use autoloading for methods, too.  Perl doesn't start lookingfor an \s-1AUTOLOAD\s0 method until it has exhausted the recursive hunt upthrough \f(CW@ISA\fR, though.  Some programmers have even been known to definea \s-1UNIVERSAL::AUTOLOAD\s0 method to trap unresolved method calls to anykind of object..Sh "Autoloaded Data Methods".IX Subsection "Autoloaded Data Methods"You probably began to get a little suspicious about the duplicatedcode way back earlier when we first showed you the Person class, andthen later the Employee class.  Each method used to access thehash fields looked virtually identical.  This should have tickledthat great programming virtue, Impatience, but for the time,we let Laziness win out, and so did nothing.  Proxy methods can curethis..PPInstead of writing a new function every time we want a new data field,we'll use the autoload mechanism to generate (actually, mimic) methods onthe fly.  To verify that we're accessing a valid member, we will checkagainst an \f(CW\*(C`_permitted\*(C'\fR (pronounced \*(L"under-permitted\*(R") field, whichis a reference to a file-scoped lexical (like a C file static) hash of permitted fields in this recordcalled \f(CW%fields\fR.  Why the underscore?  For the same reason as the _CENSUSfield we once used: as a marker that means \*(L"for internal use only\*(R"..PPHere's what the module initialization code and classconstructor will look like when taking this approach:.PP.Vb 3\&    package Person;\&    use Carp;\&    our $AUTOLOAD;  # it\*(Aqs a package global\&\&    my %fields = (\&        name        => undef,\&        age         => undef,\&        peers       => undef,\&    );\&\&    sub new {\&        my $class = shift;\&        my $self  = {\&            _permitted => \e%fields,\&            %fields,\&        };\&        bless $self, $class;\&        return $self;\&    }.Ve.PPIf we wanted our record to have default values, we could fill those inwhere current we have \f(CW\*(C`undef\*(C'\fR in the \f(CW%fields\fR hash..PPNotice how we saved a reference to our class data on the object itself?Remember that it's important to access class data through the objectitself instead of having any method reference \f(CW%fields\fR directly, or elseyou won't have a decent inheritance..PPThe real magic, though, is going to reside in our proxy method, whichwill handle all calls to undefined methods for objects of class Person(or subclasses of Person).  It has to be called \s-1AUTOLOAD\s0.  Again, it'sall caps because it's called for us implicitly by Perl itself, not bya user directly..PP.Vb 4\&    sub AUTOLOAD {\&        my $self = shift;\&        my $type = ref($self)\&                    or croak "$self is not an object";\&\&        my $name 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -