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

📄 perltooc.1

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 1
📖 第 1 页 / 共 4 页
字号:
\&    package Some_Class;\&    my %ClassData = (\&        CData1 => "",\&        CData2 => "",\&    );\&    sub CData1 {\&        shift;  # XXX: ignore calling class/object\&        $ClassData{CData1} = shift if @_;\&        return $ClassData{CData1};\&    } \&    sub CData2 {\&        shift;  # XXX: ignore calling class/object\&        $ClassData{CData2} = shift if @_;\&        return $ClassData{CData2};\&    }.Ve.PPTo make this more scalable as other class attributes are added, we canagain register closures into the package symbol table to create accessormethods for them..PP.Vb 10\&    package Some_Class;\&    my %ClassData = (\&        CData1 => "",\&        CData2 => "",\&    );\&    for my $datum (keys %ClassData) { \&        no strict "refs";\&        *$datum = sub { \&            shift;      # XXX: ignore calling class/object\&            $ClassData{$datum} = shift if @_;\&            return $ClassData{$datum};\&        };\&    }.Ve.PPRequiring even your own class to use accessor methods like anybody else isprobably a good thing.  But demanding and expecting that everyone else,be they subclass or superclass, friend or foe, will all come to yourobject through mediation is more than just a good idea.  It's absolutelycritical to the model.  Let there be in your mind no such thing as\&\*(L"public\*(R" data, nor even \*(L"protected\*(R" data, which is a seductive butultimately destructive notion.  Both will come back to bite at you.That's because as soon as you take that first step out of the solidposition in which all state is considered completely private, save from theperspective of its own accessor methods, you have violated the envelope.And, having pierced that encapsulating envelope, you shall doubtlesssomeday pay the price when future changes in the implementation breakunrelated code.  Considering that avoiding this infelicitous outcome wasprecisely why you consented to suffer the slings and arrows of obsequiousabstraction by turning to object orientation in the first place, suchbreakage seems unfortunate in the extreme..Sh "More Inheritance Concerns".IX Subsection "More Inheritance Concerns"Suppose that Some_Class were used as a base class from which to deriveAnother_Class.  If you invoke a &CData method on the derived class oron an object of that class, what do you get?  Would the derived classhave its own state, or would it piggyback on its base class's versionsof the class attributes?.PPThe answer is that under the scheme outlined above, the derived classwould \fBnot\fR have its own state data.  As before, whether you considerthis a good thing or a bad one depends on the semantics of the classesinvolved..PPThe cleanest, sanest, simplest way to address per-class state in alexical is for the derived class to override its base class's versionof the method that accesses the class attributes.  Since the actual methodcalled is the one in the object's derived class if this exists, youautomatically get per-class state this way.  Any urge to provide anunadvertised method to sneak out a reference to the \f(CW%ClassData\fR hashshould be strenuously resisted..PPAs with any other overridden method, the implementation in thederived class always has the option of invoking its base class'sversion of the method in addition to its own.  Here's an example:.PP.Vb 2\&    package Another_Class;\&    @ISA = qw(Some_Class);\&\&    my %ClassData = (\&        CData1 => "",\&    );\&\&    sub CData1 {\&        my($self, $newvalue) = @_;\&        if (@_ > 1) { \&            # set locally first\&            $ClassData{CData1} = $newvalue;  \&\&            # then pass the buck up to the first \&            # overridden version, if there is one\&            if ($self\->can("SUPER::CData1")) { \&                $self\->SUPER::CData1($newvalue);\&            }\&        }\&        return $ClassData{CData1};\&    }.Ve.PPThose dabbling in multiple inheritance might be concernedabout there being more than one override..PP.Vb 6\&    for my $parent (@ISA) {\&        my $methname = $parent . "::CData1";\&        if ($self\->can($methname)) { \&            $self\->$methname($newvalue);\&        }\&    }.Ve.PPBecause the &UNIVERSAL::can method returns a referenceto the function directly, you can use this directlyfor a significant performance improvement:.PP.Vb 5\&    for my $parent (@ISA) {\&        if (my $coderef = $self\->can($parent . "::CData1")) {\&            $self\->$coderef($newvalue);\&        }\&    }.Ve.PPIf you override \f(CW\*(C`UNIVERSAL::can\*(C'\fR in your own classes, be sure to return thereference appropriately..Sh "Locking the Door and Throwing Away the Key".IX Subsection "Locking the Door and Throwing Away the Key"As currently implemented, any code within the same scope as thefile-scoped lexical \f(CW%ClassData\fR can alter that hash directly.  Is thatok?  Is it acceptable or even desirable to allow other parts of theimplementation of this class to access class attributes directly?.PPThat depends on how careful you want to be.  Think back to the Cosmosclass.  If the &supernova method had directly altered \f(CW$Cosmos::Stars\fR or\&\f(CW$Cosmos::Cosmos{stars}\fR, then we wouldn't have been able to reuse theclass when it came to inventing a Multiverse.  So letting even the classitself access its own class attributes without the mediating intervention ofproperly designed accessor methods is probably not a good idea after all..PPRestricting access to class attributes from the class itself is usuallynot enforceable even in strongly object-oriented languages.  But in Perl,you can..PPHere's one way:.PP.Vb 1\&    package Some_Class;\&\&    {  # scope for hiding $CData1\&        my $CData1;\&        sub CData1 {\&            shift;      # XXX: unused\&            $CData1 = shift if @_;\&            return $CData1;\&        } \&    }\&\&    {  # scope for hiding $CData2\&        my $CData2;\&        sub CData2 {\&            shift;      # XXX: unused\&            $CData2 = shift if @_;\&            return $CData2;\&        } \&    }.Ve.PPNo one\*(--absolutely no one\*(--is allowed to read or write the classattributes without the mediation of the managing accessor method, sinceonly that method has access to the lexical variable it's managing.This use of mediated access to class attributes is a form of privacy farstronger than most \s-1OO\s0 languages provide..PPThe repetition of code used to create per-datum accessor methods chafesat our Laziness, so we'll again use closures to create similarmethods..PP.Vb 1\&    package Some_Class;\&\&    {  # scope for ultra\-private meta\-object for class attributes\&        my %ClassData = ( \&            CData1 => "",\&            CData2 => "",\&        );\&\&        for my $datum (keys %ClassData ) { \&            no strict "refs";    \&            *$datum = sub {\&                use strict "refs";    \&                my ($self, $newvalue) = @_;\&                $ClassData{$datum} = $newvalue if @_ > 1;\&                return $ClassData{$datum};\&            }\&        }\&\&    }.Ve.PPThe closure above can be modified to take inheritance into account usingthe &UNIVERSAL::can method and \s-1SUPER\s0 as shown previously..Sh "Translucency Revisited".IX Subsection "Translucency Revisited"The Vermin class demonstrates translucency using a package variable,eponymously named \f(CW%Vermin\fR, as its meta-object.  If you prefer touse absolutely no package variables beyond those necessary to appeaseinheritance or possibly the Exporter, this strategy is closed to you.That's too bad, because translucent attributes are an appealingtechnique, so it would be valuable to devise an implementation usingonly lexicals..PPThere's a second reason why you might wish to avoid the eponymouspackage hash.  If you use class names with double-colons in them, youwould end up poking around somewhere you might not have meant to poke..PP.Vb 4\&    package Vermin;\&    $class = "Vermin";\&    $class\->{PopCount}++;       \&    # accesses $Vermin::Vermin{PopCount}\&\&    package Vermin::Noxious;\&    $class = "Vermin::Noxious";\&    $class\->{PopCount}++;       \&    # accesses $Vermin::Noxious{PopCount}.Ve.PPIn the first case, because the class name had no double-colons, we gotthe hash in the current package.  But in the second case, instead ofgetting some hash in the current package, we got the hash \f(CW%Noxious\fR inthe Vermin package.  (The noxious vermin just invaded another package andsprayed their data around it. :\-) Perl doesn't support relative packagesin its naming conventions, so any double-colons trigger a fully-qualifiedlookup instead of just looking in the current package..PPIn practice, it is unlikely that the Vermin class had an existingpackage variable named \f(CW%Noxious\fR that you just blew away.  If you'restill mistrustful, you could always stake out your own territorywhere you know the rules, such as using Eponymous::Vermin::Noxious orHieronymus::Vermin::Boschious or Leave_Me_Alone::Vermin::Noxious as classnames instead.  Sure, it's in theory possible that someone else hasa class named Eponymous::Vermin with its own \f(CW%Noxious\fR hash, but thiskind of thing is always true.  There's no arbiter of package names.It's always the case that globals like \f(CW@Cwd::ISA\fR would collide if morethan one class uses the same Cwd package..PPIf this still leaves you with an uncomfortable twinge of paranoia,we have another solution for you.  There's nothing that says that youhave to have a package variable to hold a class meta-object, either formonadic classes or for translucent attributes.  Just code up the methodsso that they access a lexical instead..PPHere's another implementation of the Vermin class with semantics identicalto those given previously, but this time using no package variables..PP.Vb 1\&    package Vermin;\&\&\&    # Here\*(Aqs the class meta\-object, eponymously named.\&    # It holds all class data, and also all instance data \&    # so the latter can be used for both initialization \&    # and translucency.  it\*(Aqs a template.\&    my %ClassData = (                   \&        PopCount => 0,          # capital for class attributes\&        color    => "beige",    # small for instance attributes         \&    );\&\&    # constructor method\&    # invoked as class method or object method\&    sub spawn {\&        my $obclass = shift;\&        my $class   = ref($obclass) || $obclass;\&        my $self = {};\&        bless($self, $class);\&        $ClassData{PopCount}++;\&        # init fields from invoking object, or omit if \&        # invoking object is the class to provide translucency\&        %$self = %$obclass if ref $obclass;\&        return $self;\&    } \&\&    # translucent accessor for "color" attribute\&    # invoked as class method or object method\&    sub color {\&        my $self  = shift;\&\&        # handle class invocation\&        unless (ref $self) {\&            $ClassData{color} = shift if @_;\&            return $ClassData{color}\&        }\&\&        # handle object invocation\&        $self\->{color} = shift if @_;\&        if (defined $self\->{color}) {  # not exists!\&            return $self\->{color};\&        } else {\&            return $ClassData{color};\&        } \&    } \&\&    # class attribute accessor for "PopCount" attribute\&    # invoked as class method or object method\&    sub population {\&        return $ClassData{PopCount};\&    } \&\&    # instance destructor; invoked only as object method\&    sub DESTROY {\&        $ClassData{PopCount}\-\-;\&    }\&\&    # detect whether an object attribute is translucent\&    # (typically?) invoked only as object method\&    sub is_translucent {\&        my($self, $attr)  = @_;\&        $self = \e%ClassData if !ref $self;\&        return !defined $self\->{$attr};  \&    }\&\&    # test for presence of attribute in class\&    # invoked as class method or object method\&    sub has_attribute {\&        my($self, $attr)  = @_;\&        return exists $ClassData{$attr};  \&    }.Ve.SH "NOTES".IX Header "NOTES"Inheritance is a powerful but subtle device, best used only after carefulforethought and design.  Aggregation instead of inheritance is often abetter approach..PPYou can't use file-scoped lexicals in conjunction with the SelfLoaderor the AutoLoader, because they alter the lexical scope in which themodule's methods wind up getting compiled..PPThe usual mealy-mouthed package-munging doubtless applies to settingup names of object attributes.  For example, \f(CW\*(C`$self\->{ObData1}\*(C'\fRshould probably be \f(CW\*(C`$self\->{ _\|_PACKAGE_\|_ . "_ObData1" }\*(C'\fR, but thatwould just confuse the examples..SH "SEE ALSO".IX Header "SEE ALSO"perltoot, perlobj, perlmod, and perlbot..PPThe Tie::SecureHash and Class::Data::Inheritable modules from \s-1CPAN\s0 areworth checking out..SH "AUTHOR AND COPYRIGHT".IX Header "AUTHOR AND COPYRIGHT"Copyright (c) 1999 Tom Christiansen.All rights reserved..PPThis documentation is free; you can redistribute it and/or modify itunder the same terms as Perl itself..PPIrrespective of its distribution, all code examples in this fileare hereby placed into the public domain.  You are permitted andencouraged to use this code in your own programs for funor for profit as you see fit.  A simple comment in the code givingcredit would be courteous but is not required..SH "ACKNOWLEDGEMENTS".IX Header "ACKNOWLEDGEMENTS"Russ Allbery, Jon Orwant, Randy Ray, Larry Rosler, Nat Torkington,and Stephen Warren all contributed suggestions and corrections to thispiece.  Thanks especially to Damian Conway for his ideas and feedback,and without whose indirect prodding I might never have taken the timeto show others how much Perl has to offer in the way of objects onceyou start thinking outside the tiny little box that today's \*(L"popular\*(R"object-oriented languages enforce..SH "HISTORY".IX Header "HISTORY"Last edit: Sun Feb  4 20:50:28 \s-1EST\s0 2001

⌨️ 快捷键说明

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