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

📄 perltooc.pod

📁 视频监控网络部分的协议ddns,的模块的实现代码,请大家大胆指正.
💻 POD
📖 第 1 页 / 共 4 页
字号:
an object and store the attribute value directly on the class, then themeta-object's value changes, and later fetch operations on objects withuninitialized values for those attributes will retrieve the meta-object'snew values.  Objects with their own initialized values, however, won'tsee any change.Let's look at some concrete examples of using these properties before weshow how to implement them.  Suppose that a class named Some_Classhad a translucent data attribute called "color".  First you set the colorin the meta-object, then you create three objects using a constructorthat happens to be named &spawn.    use Vermin;    Vermin->color("vermilion");    $ob1 = Vermin->spawn();   	# so that's where Jedi come from    $ob2 = Vermin->spawn();       $ob3 = Vermin->spawn();      print $obj3->color();  	# prints "vermilion"Each of these objects' colors is now "vermilion", because that's themeta-object's value for that attribute, and these objects do not haveindividual color values set.Changing the attribute on one object has no effect on other objectspreviously created.    $ob3->color("chartreuse");		    print $ob3->color();  	# prints "chartreuse"    print $ob1->color();  	# prints "vermilion", translucentlyIf you now use $ob3 to spawn off another object, the new object willtake the color its parent held, which now happens to be "chartreuse".That's because the constructor uses the invoking object as its templatefor initializing attributes.  When that invoking object is theclass name, the object used as a template is the eponymous meta-object.When the invoking object is a reference to an instantiated object, the&spawn constructor uses that existing object as a template.      $ob4 = $ob3->spawn();	# $ob3 now template, not %Vermin    print $ob4->color();  	# prints "chartreuse"Any actual values set on the template object will be copied to thenew object.  But attributes undefined in the template object, beingtranslucent, will remain undefined and consequently translucent in thenew one as well.Now let's change the color attribute on the entire class:    Vermin->color("azure");	    print $ob1->color();  	# prints "azure"    print $ob2->color();  	# prints "azure"    print $ob3->color();  	# prints "chartreuse"    print $ob4->color();  	# prints "chartreuse"That color change took effect only in the first pair of objects, whichwere still translucently accessing the meta-object's values.  The secondpair had per-object initialized colors, and so didn't change.One important question remains.  Changes to the meta-object are reflectedin translucent attributes in the entire class, but what aboutchanges to discrete objects?  If you change the color of $ob3, does thevalue of $ob4 see that change?  Or vice-versa.  If you change the colorof $ob4, does then the value of $ob3 shift?    $ob3->color("amethyst");		    print $ob3->color();  	# prints "amethyst"    print $ob4->color();  	# hmm: "chartreuse" or "amethyst"?While one could argue that in certain rare cases it should, let's notdo that.  Good taste aside, we want the answer to the question posed inthe comment above to be "chartreuse", not "amethyst".  So we'll treatthese attributes similar to the way process attributes like environmentvariables, user and group IDs, or the current working directory aretreated across a fork().  You can change only yourself, but you will seethose changes reflected in your unspawned children.  Changes to one objectwill propagate neither up to the parent nor down to any existing child objects.Those objects made later, however, will see the changes.If you have an object with an actual attribute value, and you want tomake that object's attribute value translucent again, what do you do?Let's design the class so that when you invoke an accessor method withC<undef> as its argument, that attribute returns to translucency.    $ob4->color(undef);		# back to "azure"Here's a complete implementation of Vermin as described above.    package Vermin;    # here's the class meta-object, eponymously named.    # it holds all class attributes, and also all instance attributes     # so the latter can be used for both initialization     # and translucency.    our %Vermin = (   		# our() is new to perl5.6	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);	$class->{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;	my $class = ref($self) || $self;	# handle class invocation	unless (ref $self) {	    $class->{color} = shift if @_;	    return $class->{color}	}	# handle object invocation	$self->{color} = shift if @_;	if (defined $self->{color}) {  # not exists!	    return $self->{color};	} else {	    return $class->{color};	}     }     # accessor for "PopCount" class attribute    # invoked as class method or object method    # but uses object solely to locate meta-object    sub population {	my $obclass = shift;	my $class   = ref($obclass) || $obclass;	return $class->{PopCount};    }     # instance destructor    # invoked only as object method    sub DESTROY {	my $self  = shift;	my $class = ref $self;	$class->{PopCount}--;    }Here are a couple of helper methods that might be convenient.  They aren'taccessor methods at all.  They're used to detect accessibility of dataattributes.  The &is_translucent method determines whether a particularobject attribute is coming from the meta-object.  The &has_attributemethod detects whether a class implements a particular property at all.It could also be used to distinguish undefined properties from non-existentones.    # detect whether an object attribute is translucent    # (typically?) invoked only as object method    sub is_translucent {	my($self, $attr)  = @_;	return !defined $self->{$attr};      }    # test for presence of attribute in class    # invoked as class method or object method    sub has_attribute {	my($self, $attr)  = @_;	my $class = ref($self) || $self;	return exists $class->{$attr};      } If you prefer to install your accessors more generically, you can makeuse of the upper-case versus lower-case convention to register into thepackage appropriate methods cloned from generic closures.    for my $datum (keys %{ +__PACKAGE__ }) {	*$datum = ($datum =~ /^[A-Z]/)	    ? sub {  # install class accessor		    my $obclass = shift;		    my $class   = ref($obclass) || $obclass;		    return $class->{$datum};		  }	    : sub { # install translucent accessor		    my $self  = shift;		    my $class = ref($self) || $self;		    unless (ref $self) {			$class->{$datum} = shift if @_;			return $class->{$datum}		    }		    $self->{$datum} = shift if @_;		    return defined $self->{$datum}			? $self  -> {$datum}			: $class -> {$datum}		  }     }Translations of this closure-based approach into C++, Java, and Pythonhave been left as exercises for the reader.  Be sure to send us mail assoon as you're done.=head1 Class Data as Lexical Variables=head2 Privacy and Responsibility Unlike conventions used by some Perl programmers, in the previousexamples, we didn't prefix the package variables used for class attributeswith an underscore, nor did we do so for the names of the hash keys usedfor instance attributes.  You don't need little markers on data names tosuggest nominal privacy on attribute variables or hash keys, because theseare B<already> notionally private!  Outsiders have no business whatsoeverplaying with anything within a class save through the mediated access ofits documented interface; in other words, through method invocations.And not even through just any method, either.  Methods that begin withan underscore are traditionally considered off-limits outside the class.If outsiders skip the documented method interface to poke around theinternals of your class and end up breaking something, that's not yourfault--it's theirs.Perl believes in individual responsibility rather than mandated control.Perl respects you enough to let you choose your own preferred level ofpain, or of pleasure.  Perl believes that you are creative, intelligent,and capable of making your own decisions--and fully expects you totake complete responsibility for your own actions.  In a perfect world,these admonitions alone would suffice, and everyone would be intelligent,responsible, happy, and creative.  And careful.  One probably shouldn'tforget careful, and that's a good bit harder to expect.  Even Einsteinwould take wrong turns by accident and end up lost in the wrong partof town.Some folks get the heebie-jeebies when they see package variableshanging out there for anyone to reach over and alter them.  Some folkslive in constant fear that someone somewhere might do something wicked.The solution to that problem is simply to fire the wicked, of course.But unfortunately, it's not as simple as all that.  These cautioustypes are also afraid that they or others will do something not somuch wicked as careless, whether by accident or out of desperation.If we fire everyone who ever gets careless, pretty soon there won't beanybody left to get any work done.Whether it's needless paranoia or sensible caution, this uneasiness canbe a problem for some people.  We can take the edge off their discomfortby providing the option of storing class attributes as lexical variablesinstead of as package variables.  The my() operator is the source ofall privacy in Perl, and it is a powerful form of privacy indeed.It is widely perceived, and indeed has often been written, that Perlprovides no data hiding, that it affords the class designer no privacynor isolation, merely a rag-tag assortment of weak and unenforceablesocial conventions instead.  This perception is demonstrably false andeasily disproven.  In the next section, we show how to implement formsof privacy that are far stronger than those provided in nearly anyother object-oriented language.=head2 File-Scoped LexicalsA lexical variable is visible only through the end of its static scope.That means that the only code able to access that variable is coderesiding textually below the my() operator through the end of its blockif it has one, or through the end of the current file if it doesn't.Starting again with our simplest example given at the start of thisdocument, we replace our() variables with my() versions.    package Some_Class;    my($CData1, $CData2);   # file scope, not in any package    sub CData1 {	shift;	# XXX: ignore calling class/object	$CData1 = shift if @_;	return $CData1;    }     sub CData2 {	shift;	# XXX: ignore calling class/object	$CData2 = shift if @_;	return $CData2;    } So much for that old $Some_Class::CData1 package variable and its brethren!Those are gone now, replaced with lexicals.  No one outside thescope can reach in and alter the class state without resorting to thedocumented interface.  Not even subclasses or superclasses ofthis one have unmediated access to $CData1.  They have to invoke the &CData1method against Some_Class or an instance thereof, just like anybody else.To be scrupulously honest, that last statement assumes you haven't packedseveral classes together into the same file scope, nor strewn your classimplementation across several different files.  Accessibility of thosevariables is based uniquely on the static file scope.  It has nothing todo with the package.  That means that code in a different file butthe same package (class) could not access those variables, yet code in thesame file but a different package (class) could.  There are sound reasonswhy we usually suggest a one-to-one mapping between files and packagesand modules and classes.  You don't have to stick to this suggestion ifyou really know what you're doing, but you're apt to confuse yourselfotherwise, especially at first.If you'd like to aggregate your class attributes into one lexically scoped,composite structure, you're perfectly free to do so.    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};    } To make this more scalable as other class attributes are added, we canagain register closures into the package symbol table to create accessormethods for them.    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};	};    }

⌨️ 快捷键说明

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