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

📄 ch13_13.htm

📁 By Tom Christiansen and Nathan Torkington ISBN 1-56592-243-3 First Edition, published August 1998
💻 HTM
字号:
<HTML><HEAD><TITLE>Recipe 13.12. Solving the Data Inheritance Problem (Perl Cookbook)</TITLE><METANAME="DC.title"CONTENT="Perl Cookbook"><METANAME="DC.creator"CONTENT="Tom Christiansen &amp; Nathan Torkington"><METANAME="DC.publisher"CONTENT="O'Reilly &amp; Associates, Inc."><METANAME="DC.date"CONTENT="1999-07-02T01:42:28Z"><METANAME="DC.type"CONTENT="Text.Monograph"><METANAME="DC.format"CONTENT="text/html"SCHEME="MIME"><METANAME="DC.source"CONTENT="1-56592-243-3"SCHEME="ISBN"><METANAME="DC.language"CONTENT="en-US"><METANAME="generator"CONTENT="Jade 1.1/O'Reilly DocBook 3.0 to HTML 4.0"><LINKREV="made"HREF="mailto:online-books@oreilly.com"TITLE="Online Books Comments"><LINKREL="up"HREF="ch13_01.htm"TITLE="13. Classes, Objects, and Ties"><LINKREL="prev"HREF="ch13_12.htm"TITLE="13.11. Generating Attribute Methods Using AUTOLOAD"><LINKREL="next"HREF="ch13_14.htm"TITLE="13.13. Coping with Circular Data Structures"></HEAD><BODYBGCOLOR="#FFFFFF"><img alt="Book Home" border="0" src="gifs/smbanner.gif" usemap="#banner-map" /><map name="banner-map"><area shape="rect" coords="1,-2,616,66" href="index.htm" alt="Perl Cookbook"><area shape="rect" coords="629,-11,726,25" href="jobjects/fsearch.htm" alt="Search this book" /></map><div class="navbar"><p><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch13_12.htm"TITLE="13.11. Generating Attribute Methods Using AUTOLOAD"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 13.11. Generating Attribute Methods Using AUTOLOAD"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><B><FONTFACE="ARIEL,HELVETICA,HELV,SANSERIF"SIZE="-1"><ACLASS="chapter"REL="up"HREF="ch13_01.htm"TITLE="13. Classes, Objects, and Ties"></A></FONT></B></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch13_14.htm"TITLE="13.13. Coping with Circular Data Structures"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 13.13. Coping with Circular Data Structures"BORDER="0"></A></TD></TR></TABLE></DIV><DIVCLASS="sect1"><H2CLASS="sect1"><ACLASS="title"NAME="ch13-25082">13.12. Solving the Data Inheritance Problem</A></H2><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch13-pgfId-1495">Problem<ACLASS="indexterm"NAME="ch13-idx-1000004598-0"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-1"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-2"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-3"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-4"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-5"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-6"></A><ACLASS="indexterm"NAME="ch13-idx-1000004598-7"></A></A></H3><PCLASS="para">You want to inherit from an existing class, augmenting it with a few extra methods, but you don't know which data fields your parent class is using. How can you safely carve out your own namespace in the object hash without trampling on any ancestors?</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch13-pgfId-1501">Solution</A></H3><PCLASS="para">Prepend each of your fieldnames with your own class name and a distinctive separator, such as an underscore or two.</P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch13-pgfId-1507">Discussion</A></H3><PCLASS="para">An irksome problem lurks within the normal Perl OO strategy. The exact class representation must be known, violating the veil of abstraction. The subclass has to get unnaturally chummy with all its parent classes, recursively.</P><PCLASS="para">We'll pretend we're a big happy object-oriented family and that everyone always uses hashes for objects, thus dodging the problem of a class choosing an array representation but inheriting from one that instead uses a hash model. (The solution to that problem is aggregation and delegation, as shown in <ICLASS="filename">perlbot </I>(1).) Even with this assumption, an inherited class can't safely use a key in the hash. Even if we agree to use only method calls to access attributes we don't ourselves set, how do we know that we aren't setting a key that a parent class is using? Imagine wanting to use a <CODECLASS="literal">count</CODE> field, but unbeknownst to you, your great-great-grandparent class is using the same thing. Using <CODECLASS="literal">_count</CODE> to indicate nominal privacy won't help, since gramps might try the same trick.</P><PCLASS="para">One reasonable approach is to prefix your own data members with your package name. Thus if you were class Employee and wanted an <CODECLASS="literal">age</CODE> field, for safety's sake you could use <CODECLASS="literal">Employee_age</CODE> instead. Here's a sample access method:</P><PRECLASS="programlisting">sub Employee::age {    my $self = shift;    $self-&gt;{Employee_age} = shift if @_;    return $self-&gt;{Employee_age};} </PRE><PCLASS="para">In the spirit of the Class::Struct module described in <ACLASS="xref"HREF="ch13_06.htm"TITLE="Using Classes as Structs">Recipe 13.5</A>, here's a more turnkey solution to the problem. Imagine one file with:</P><PRECLASS="programlisting">package Person;use Class::Attributes;  # see explanation belowmkattr qw(name age peers parent);</PRE><PCLASS="para">and another like this:</P><PRECLASS="programlisting">package Employee;@ISA = qw(Person);use Class::Attributes;mkattr qw(salary age boss);</PRE><PCLASS="para">Notice that they both have an <CODECLASS="literal">age</CODE> attribute? If those are to be logically separate, we can't use <CODECLASS="literal">$self-&gt;{age}</CODE>, even for ourselves inside the module! Here's an implementation of the <CODECLASS="literal">Class::Attributes::mkattr</CODE> function that solves this:</P><PRECLASS="programlisting">package Class::Attributes;use strict;use Carp;use Exporter ();use vars qw(@ISA @EXPORT);@ISA = qw(Exporter);@EXPORT = qw(mkattr);sub mkattr {    my $hispack = caller();    for my $attr (@_) {        my($field, $method);        $method = &quot;${hispack}::$attr&quot;;        ($field = $method) =~ s/:/_/g;         no strict 'refs'; # here comes the kluglich bit        *$method = sub {            my $self = shift;            confess &quot;too many arguments&quot; if @_ &gt; 1;            $self-&gt;{$field} = shift if @_;            return $self-&gt;{$field};           };    } } 1;</PRE><PCLASS="para">This way <CODECLASS="literal">$self-&gt;{Person_age}</CODE> and <CODECLASS="literal">$self-&gt;{Employee_age}</CODE> remain separate. The only funniness is that <CODECLASS="literal">$obj-&gt;age</CODE> would only get the first one. Now, you could write <CODECLASS="literal">$obj-&gt;Person::age</CODE> and <CODECLASS="literal">$obj-&gt;Employee::age</CODE> to distinguish these, but well-written Perl code shouldn't use double colons to specify an exact package except under extreme duress. If you really are forced to, perhaps that library could have been better designed.</P><PCLASS="para">If you didn't want to write it that way, then from inside class Person, just use <CODECLASS="literal">age($self)</CODE> and you'll always get Person's version, whereas from inside class Employee, <CODECLASS="literal">age($self)</CODE> would get Employee's version. That's because it's a function call, not a method call.<ACLASS="indexterm"NAME="ch13-idx-1000004605-0"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-1"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-2"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-3"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-4"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-5"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-6"></A><ACLASS="indexterm"NAME="ch13-idx-1000004605-7"></A></P></DIV><DIVCLASS="sect2"><H3CLASS="sect2"><ACLASS="title"NAME="ch13-pgfId-1000004048">See Also</A></H3><PCLASS="para">The documentation on the <CODECLASS="literal">use</CODE> <CODECLASS="literal">fields</CODE> and <CODECLASS="literal">use</CODE> <CODECLASS="literal">base</CODE> pragmas, standard as of Perl 5.005; <ACLASS="xref"HREF="ch10_15.htm"TITLE="Redefining a Function">Recipe 10.14</A></P></DIV></DIV><DIVCLASS="htmlnav"><P></P><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><TABLEWIDTH="684"BORDER="0"CELLSPACING="0"CELLPADDING="0"><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch13_12.htm"TITLE="13.11. Generating Attribute Methods Using AUTOLOAD"><IMGSRC="../gifs/txtpreva.gif"ALT="Previous: 13.11. Generating Attribute Methods Using AUTOLOAD"BORDER="0"></A></TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="book"HREF="index.htm"TITLE="Perl Cookbook"><IMGSRC="../gifs/txthome.gif"ALT="Perl Cookbook"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228"><ACLASS="sect1"HREF="ch13_14.htm"TITLE="13.13. Coping with Circular Data Structures"><IMGSRC="../gifs/txtnexta.gif"ALT="Next: 13.13. Coping with Circular Data Structures"BORDER="0"></A></TD></TR><TR><TDALIGN="LEFT"VALIGN="TOP"WIDTH="228">13.11. Generating Attribute Methods Using AUTOLOAD</TD><TDALIGN="CENTER"VALIGN="TOP"WIDTH="228"><ACLASS="index"HREF="index/index.htm"TITLE="Book Index"><IMGSRC="../gifs/index.gif"ALT="Book Index"BORDER="0"></A></TD><TDALIGN="RIGHT"VALIGN="TOP"WIDTH="228">13.13. Coping with Circular Data Structures</TD></TR></TABLE><HRALIGN="LEFT"WIDTH="684"TITLE="footer"><FONTSIZE="-1"></DIV<!-- LIBRARY NAV BAR --> <img src="../gifs/smnavbar.gif" usemap="#library-map" border="0" alt="Library Navigation Links"><p> <a href="copyrght.htm">Copyright &copy; 2002</a> O'Reilly &amp; Associates. All rights reserved.</font> </p> <map name="library-map"> <area shape="rect" coords="1,0,85,94" href="../index.htm"><area shape="rect" coords="86,1,178,103" href="../lwp/index.htm"><area shape="rect" coords="180,0,265,103" href="../lperl/index.htm"><area shape="rect" coords="267,0,353,105" href="../perlnut/index.htm"><area shape="rect" coords="354,1,446,115" href="../prog/index.htm"><area shape="rect" coords="448,0,526,132" href="../tk/index.htm"><area shape="rect" coords="528,1,615,119" href="../cookbook/index.htm"><area shape="rect" coords="617,0,690,135" href="../pxml/index.htm"></map> </BODY></HTML>

⌨️ 快捷键说明

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