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

📄 perltooc.pod

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 POD
📖 第 1 页 / 共 4 页
字号:
Even 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.    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 \%$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};	}    }=head2 Indirect References to Class DataA 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 L<perltoot> andL<perlbot>, but there may be variations in the example below that youhaven't thought of before.    package Some_Class;    our($CData1, $CData2);      	# our() is new to perl5.6    sub new {	my $obclass = shift;	return bless my $self = {	    ObData1 => "",	    ObData2 => "",	    CData1  => \$CData1,	    CData2  => \$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}			: \$CData1;	$$dataref = shift if @_;	return $$dataref;    }     sub CData2 {	my $self = shift;	my $dataref = ref $self			? $self->{CData2}			: \$CData2;	$$dataref = shift if @_;	return $$dataref;    } As 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.	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 \%$class;	} 	sub new {	    my $obclass  = shift;	    my $classobj = $obclass->_classobj();	    bless my $self = {		ObData1 => "",		ObData2 => "",		CData1  => \$classobj->{CData1},		CData2  => \$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;	} Not 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.You 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.)There'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.=head2 Monadic ClassesSome 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 @ISA array to mention"Exporter".  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.Another sort of class that pops up from time to time is one that supportsa unique instance.  Such classes are called I<monadic classes>, or lessformally, I<singletons> or I<highlander classes>.If 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:    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't 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's 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();Hold 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 $self 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, C<%$self> is really accessing the %Cosmospackage variable.If 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.Imagine 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.That's what code reuse via subclassing is all about.  Look how shortthe new code is:    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;Because we were careful to be good little creators when we designed ourCosmos class, we can now reuse it without touching a single line of codewhen it comes time to write our Multiverse class.  The same code thatworked when invoked as a class method continues to work perfectly wellwhen invoked against separate instances of a derived class.The astonishing thing about the Cosmos class above is that the valuereturned by the &bigbang "constructor" is not a reference to a blessedobject at all.  It's just the class's own name.  A class name is, forvirtually all intents and purposes, a perfectly acceptable object.It has state, behavior, and identity, the three crucial componentsof an object system.  It even manifests inheritance, polymorphism,and encapsulation.  And what more can you ask of an object?To understand object orientation in Perl, it's important to recognize theunification of what other programming languages might think of as classmethods and object methods into just plain methods.  "Class methods"and "object methods" are distinct only in the compartmentalizing mindof the Perl programmer, not in the Perl language itself.Along those same lines, a constructor is nothing special either, whichis one reason why Perl has no pre-ordained name for them.  "Constructor"is just an informal term loosely used to describe a method that returnsa scalar value that you can make further method calls against.  So longas it's either a class name or an object reference, that's good enough.It doesn't even have to be a reference to a brand new object.You can have as many--or as few--constructors as you want, and you canname them whatever you care to.  Blindly and obediently using new()for each and every constructor you ever write is to speak Perl withsuch a severe C++ accent that you do a disservice to both languages.There's no reason to insist that each class have but one constructor,or that a constructor be named new(), or that a constructor beused solely as a class method and not an object method.The next section shows how useful it can be to further distance ourselvesfrom any formal distinction between class method calls and object methodcalls, both in constructors and in accessor methods.=head2 Translucent AttributesA package's eponymous hash can be used for more than just containingper-class, global state data.  It can also serve as a sort of templatecontaining default settings for object attributes.  These defaultsettings can then be used in constructors for initialization of aparticular object.  The class's eponymous hash can also be used toimplement I<translucent attributes>.  A translucent attribute is onethat has a class-wide default.  Each object can set its own value for theattribute, in which case C<< $object->attribute() >> returns that value.But if no value has been set, then C<< $object->attribute() >> returnsthe class-wide default.We'll apply something of a copy-on-write approach to these translucentattributes.  If you're just fetching values from them, you gettranslucency.  But if you store a new value to them, that new value isset on the current object.  On the other hand, if you use the class as

⌨️ 快捷键说明

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