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

📄 perltooc.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 4 页
字号:
.PPOnce again we temporarily disable the strict references ban, becauseotherwise we couldn't use the fully-qualified symbolic name forthe package global.  This is perfectly reasonable: since all packagevariables by definition live in a package, there's nothing wrong withaccessing them via that package's symbol table.  That's what it's therefor (well, somewhat)..PPWhat about just using a single hash for everything and then cloningmethods?  What would that look like?  The only difference would be theclosure used to produce new method entries for the class's symbol table..PP.Vb 8\&    no strict "refs";   \&    *$datum = sub {\&        my $obclass = shift;    \&        my $class   = ref($obclass) || $obclass;\&        my $varname = $class . "::ClassData";\&        $varname\->{$datum} = shift if @_;\&        return $varname\->{$datum};\&    }.Ve.Sh "The Eponymous Meta-Object".IX Subsection "The Eponymous Meta-Object"It could be argued that the \f(CW%ClassData\fR hash in the previous example isneither the most imaginative nor the most intuitive of names.  Is theresomething else that might make more sense, be more useful, or both?.PPAs it happens, yes, there is.  For the \*(L"class meta-object\*(R", we'll usea package variable of the same name as the package itself.  Within thescope of a package Some_Class declaration, we'll use the eponymouslynamed hash \f(CW%Some_Class\fR as that class's meta-object.  (Using an eponymouslynamed hash is somewhat reminiscent of classes that name their constructorseponymously in the Python or \*(C+ fashion.  That is, class Some_Class woulduse &Some_Class::Some_Class as a constructor, probably even exporting thatname as well.  The StrNum class in Recipe 13.14 in \fIThe Perl Cookbook\fRdoes this, if you're looking for an example.).PPThis predictable approach has many benefits, including having a well-knownidentifier to aid in debugging, transparent persistence,or checkpointing.  It's also the obvious name for monadic classes andtranslucent attributes, discussed later..PPHere's an example of such a class.  Notice how the name of the hash storing the meta-object is the same as the name of the packageused to implement the class..PP.Vb 2\&    package Some_Class;\&    use strict;\&\&    # create class meta\-object using that most perfect of names\&    our %Some_Class = (         # our() is new to perl5.6\&        CData1 => "",\&        CData2 => "",\&    );\&\&    # this accessor is calling\-package\-relative\&    sub CData1 {\&        my $obclass = shift;    \&        my $class   = ref($obclass) || $obclass;\&        no strict "refs";       # to access eponymous meta\-object\&        $class\->{CData1} = shift if @_;\&        return $class\->{CData1};\&    }\&\&    # but this accessor is not\&    sub CData2 {\&        shift;                  # XXX: ignore calling class/object\&        no strict "refs";       # to access eponymous meta\-object\&        _\|_PACKAGE_\|_ \-> {CData2} = shift if @_;\&        return _\|_PACKAGE_\|_ \-> {CData2};\&    }.Ve.PPIn the second accessor method, the _\|_PACKAGE_\|_ notation was used fortwo reasons.  First, to avoid hardcoding the literal package namein the code in case we later want to change that name.  Second, toclarify to the reader that what matters here is the package currentlybeing compiled into, not the package of the invoking object or class.If the long sequence of non-alphabetic characters bothers you, you canalways put the _\|_PACKAGE_\|_ in a variable first..PP.Vb 7\&    sub CData2 {\&        shift;                  # XXX: ignore calling class/object\&        no strict "refs";       # to access eponymous meta\-object\&        my $class = _\|_PACKAGE_\|_;\&        $class\->{CData2} = shift if @_;\&        return $class\->{CData2};\&    }.Ve.PPEven though we're using symbolic references for good not evil, somefolks tend to become unnerved when they see so many places with strictref checking disabled.  Given a symbolic reference, you can alwaysproduce a real reference (the reverse is not true, though).  So we'llcreate a subroutine that does this conversion for us.  If invoked as afunction of no arguments, it returns a reference to the compiling class'seponymous hash.  Invoked as a class method, it returns a reference tothe eponymous hash of its caller.  And when invoked as an object method,this function returns a reference to the eponymous hash for whateverclass the object belongs to..PP.Vb 2\&    package Some_Class;\&    use strict;\&\&    our %Some_Class = (         # our() is new to perl5.6\&        CData1 => "",\&        CData2 => "",\&    );\&\&    # tri\-natured: function, class method, or object method\&    sub _classobj {\&        my $obclass = shift || _\|_PACKAGE_\|_;\&        my $class   = ref($obclass) || $obclass;\&        no strict "refs";   # to convert sym ref to real one\&        return \e%$class;\&    } \&\&    for my $datum (keys %{ _classobj() } ) { \&        # turn off strict refs so that we can\&        # register a method in the symbol table\&        no strict "refs";       \&        *$datum = sub {\&            use strict "refs";\&            my $self = shift\->_classobj();\&            $self\->{$datum} = shift if @_;\&            return $self\->{$datum};\&        }\&    }.Ve.Sh "Indirect References to Class Data".IX Subsection "Indirect References to Class Data"A reasonably common strategy for handling class attributes is to storea reference to each package variable on the object itself.  This isa strategy you've probably seen before, such as in perltoot andperlbot, but there may be variations in the example below that youhaven't thought of before..PP.Vb 2\&    package Some_Class;\&    our($CData1, $CData2);              # our() is new to perl5.6\&\&    sub new {\&        my $obclass = shift;\&        return bless my $self = {\&            ObData1 => "",\&            ObData2 => "",\&            CData1  => \e$CData1,\&            CData2  => \e$CData2,\&        } => (ref $obclass || $obclass);\&    } \&\&    sub ObData1 {\&        my $self = shift;\&        $self\->{ObData1} = shift if @_;\&        return $self\->{ObData1};\&    } \&\&    sub ObData2 {\&        my $self = shift;\&        $self\->{ObData2} = shift if @_;\&        return $self\->{ObData2};\&    } \&\&    sub CData1 {\&        my $self = shift;\&        my $dataref = ref $self\&                        ? $self\->{CData1}\&                        : \e$CData1;\&        $$dataref = shift if @_;\&        return $$dataref;\&    } \&\&    sub CData2 {\&        my $self = shift;\&        my $dataref = ref $self\&                        ? $self\->{CData2}\&                        : \e$CData2;\&        $$dataref = shift if @_;\&        return $$dataref;\&    }.Ve.PPAs written above, a derived class will inherit these methods, whichwill consequently access package variables in the base class's package.This is not necessarily expected behavior in all circumstances.  Here's anexample that uses a variable meta-object, taking care to access theproper package's data..PP.Vb 2\&        package Some_Class;\&        use strict;\&\&        our %Some_Class = (     # our() is new to perl5.6\&            CData1 => "",\&            CData2 => "",\&        );\&\&        sub _classobj {\&            my $self  = shift;\&            my $class = ref($self) || $self;\&            no strict "refs";\&            # get (hard) ref to eponymous meta\-object\&            return \e%$class;\&        } \&\&        sub new {\&            my $obclass  = shift;\&            my $classobj = $obclass\->_classobj();\&            bless my $self = {\&                ObData1 => "",\&                ObData2 => "",\&                CData1  => \e$classobj\->{CData1},\&                CData2  => \e$classobj\->{CData2},\&            } => (ref $obclass || $obclass);\&            return $self;\&        } \&\&        sub ObData1 {\&            my $self = shift;\&            $self\->{ObData1} = shift if @_;\&            return $self\->{ObData1};\&        } \&\&        sub ObData2 {\&            my $self = shift;\&            $self\->{ObData2} = shift if @_;\&            return $self\->{ObData2};\&        } \&\&        sub CData1 {\&            my $self = shift;\&            $self = $self\->_classobj() unless ref $self;\&            my $dataref = $self\->{CData1};\&            $$dataref = shift if @_;\&            return $$dataref;\&        } \&\&        sub CData2 {\&            my $self = shift;\&            $self = $self\->_classobj() unless ref $self;\&            my $dataref = $self\->{CData2};\&            $$dataref = shift if @_;\&            return $$dataref;\&        }.Ve.PPNot only are we now strict refs clean, using an eponymous meta-objectseems to make the code cleaner.  Unlike the previous version, this onedoes something interesting in the face of inheritance: it accesses theclass meta-object in the invoking class instead of the one into whichthe method was initially compiled..PPYou can easily access data in the class meta-object, makingit easy to dump the complete class state using an external mechanism suchas when debugging or implementing a persistent class.  This works becausethe class meta-object is a package variable, has a well-known name, andclusters all its data together.  (Transparent persistenceis not always feasible, but it's certainly an appealing idea.).PPThere's still no check that object accessor methods have not beeninvoked on a class name.  If strict ref checking is enabled, you'dblow up.  If not, then you get the eponymous meta-object.  What you dowith\*(--or about\*(--this is up to you.  The next two sections demonstrateinnovative uses for this powerful feature..Sh "Monadic Classes".IX Subsection "Monadic Classes"Some of the standard modules shipped with Perl provide class interfaceswithout any attribute methods whatsoever.  The most commonly used modulenot numbered amongst the pragmata, the Exporter module, is a class withneither constructors nor attributes.  Its job is simply to provide astandard interface for modules wishing to export part of their namespaceinto that of their caller.  Modules use the Exporter's &import method bysetting their inheritance list in their package's \f(CW@ISA\fR array to mention\&\*(L"Exporter\*(R".  But class Exporter provides no constructor, so you can'thave several instances of the class.  In fact, you can't have any\*(--itjust doesn't make any sense.  All you get is its methods.  Its interfacecontains no statefulness, so state data is wholly superfluous..PPAnother sort of class that pops up from time to time is one that supportsa unique instance.  Such classes are called \fImonadic classes\fR, or lessformally, \fIsingletons\fR or \fIhighlander classes\fR..PPIf a class is monadic, where do you store its state, that is,its attributes?  How do you make sure that there's never more thanone instance?  While you could merely use a slew of package variables,it's a lot cleaner to use the eponymously named hash.  Here's a completeexample of a monadic class:.PP.Vb 2\&    package Cosmos;\&    %Cosmos = ();\&\&    # accessor method for "name" attribute\&    sub name {\&        my $self = shift;\&        $self\->{name} = shift if @_;\&        return $self\->{name};\&    } \&\&    # read\-only accessor method for "birthday" attribute\&    sub birthday {\&        my $self = shift;\&        die "can\*(Aqt reset birthday" if @_;  # XXX: croak() is better\&        return $self\->{birthday};\&    } \&\&    # accessor method for "stars" attribute\&    sub stars {\&        my $self = shift;\&        $self\->{stars} = shift if @_;\&        return $self\->{stars};\&    } \&\&    # oh my \- one of our stars just went out!\&    sub supernova {\&        my $self = shift;\&        my $count = $self\->stars();\&        $self\->stars($count \- 1) if $count > 0;\&    } \&\&    # constructor/initializer method \- fix by reboot\&    sub bigbang { \&        my $self = shift;\&        %$self = (\&            name         => "the world according to tchrist",\&            birthday     => time(),\&            stars        => 0,\&        );\&        return $self;       # yes, it\*(Aqs probably a class.  SURPRISE!\&    }\&\&    # After the class is compiled, but before any use or require \&    # returns, we start off the universe with a bang.  \&    _\|_PACKAGE_\|_ \-> bigbang();.Ve.PPHold on, that doesn't look like anything special.  Those attributeaccessors look no different than they would if this were a regular classinstead of a monadic one.  The crux of the matter is there's nothingthat says that \f(CW$self\fR must hold a reference to a blessed object.  It merelyhas to be something you can invoke methods on.  Here the package nameitself, Cosmos, works as an object.  Look at the &supernova method.  Is thata class method or an object method?  The answer is that static analysiscannot reveal the answer.  Perl doesn't care, and neither should you.In the three attribute methods, \f(CW%$self\fR is really accessing the \f(CW%Cosmos\fRpackage variable..PPIf like Stephen Hawking, you posit the existence of multiple, sequential,and unrelated universes, then you can invoke the &bigbang method yourselfat any time to start everything all over again.  You might think of&bigbang as more of an initializer than a constructor, since the functiondoesn't allocate new memory; it only initializes what's already there.But like any other constructor, it does return a scalar value to usefor later method invocations..PPImagine that some day in the future, you decide that one universe justisn't enough.  You could write a new class from scratch, but you alreadyhave an existing class that does what you want\*(--except that it's monadic,and you want more than just one cosmos..PPThat's what code reuse via subclassing is all about.  Look how shortthe new code is:.PP.Vb 3\&    package Multiverse;\&    use Cosmos;\&    @ISA = qw(Cosmos);\&\&    sub new {\&        my $protoverse = shift;\&        my $class      = ref($protoverse) || $protoverse;\&        my $self       = {};\&        return bless($self, $class)\->bigbang();\&    } \&    1;

⌨️ 快捷键说明

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