📄 ch12_04.htm
字号:
<html><head><title>Object Construction (Programming Perl)</title><!-- STYLESHEET --><link rel="stylesheet" type="text/css" href="../style/style1.css"><!-- METADATA --><!--Dublin Core Metadata--><meta name="DC.Creator" content=""><meta name="DC.Date" content=""><meta name="DC.Format" content="text/xml" scheme="MIME"><meta name="DC.Generator" content="XSLT stylesheet, xt by James Clark"><meta name="DC.Identifier" content=""><meta name="DC.Language" content="en-US"><meta name="DC.Publisher" content="O'Reilly & Associates, Inc."><meta name="DC.Source" content="" scheme="ISBN"><meta name="DC.Subject.Keyword" content=""><meta name="DC.Title" content="Object Construction"><meta name="DC.Type" content="Text.Monograph"></head><body><!-- START OF BODY --><!-- TOP BANNER --><img src="gifs/smbanner.gif" usemap="#banner-map" border="0" alt="Book Home"><map name="banner-map"><AREA SHAPE="RECT" COORDS="0,0,466,71" HREF="index.htm" ALT="Programming Perl"><AREA SHAPE="RECT" COORDS="467,0,514,18" HREF="jobjects/fsearch.htm" ALT="Search this book"></map><!-- TOP NAV BAR --><div class="navbar"><table width="515" border="0"><tr><td align="left" valign="top" width="172"><a href="ch12_03.htm"><img src="../gifs/txtpreva.gif" alt="Previous" border="0"></a></td><td align="center" valign="top" width="171"><a href="ch12_01.htm">Chapter 12: Objects</a></td><td align="right" valign="top" width="172"><a href="ch12_05.htm"><img src="../gifs/txtnexta.gif" alt="Next" border="0"></a></td></tr></table></div><hr width="515" align="left"><!-- SECTION BODY --><h2 class="sect1">12.4. Object Construction</h2><a name="INDEX-2401"></a><a name="INDEX-2402"></a><a name="INDEX-2403"></a><a name="INDEX-2404"></a><p>All objects are references, but not all references are objects. Areference won't work as an object unless its referent is speciallymarked to tell Perl what package it belongs to. The act of marking areferent with a package name--and therefore, its class, since a classis just a package--is known as <em class="emphasis">blessing</em>. You can think of theblessing as turning a reference into an object, although it's moreaccurate to say that it turns the reference into an object reference.</p><p><a name="INDEX-2405"></a>The <tt class="literal">bless</tt> function takes either one or two arguments. The firstargument is a reference and the second is the package to bless thereferent into. If the second argument is omitted, the current packageis used.<blockquote><pre class="programlisting">$obj = { }; # Get reference to anonymous hash.bless($obj); # Bless hash into current package.bless($obj, "Critter"); # Bless hash into class Critter.</pre></blockquote><a name="INDEX-2406"></a><a name="INDEX-2407"></a><a name="INDEX-2408"></a><a name="INDEX-2409"></a>Here we've used a reference to an anonymous hash, which is what peopleusually use as the data structure for their objects. Hashes areextremely flexible, after all. But allow us to emphasize that you canbless a reference to anything you can make a reference to in Perl,including scalars, arrays, subroutines, and typeglobs. You can evenbless a reference to a package's symbol table hash if you can think ofa good reason to. (Or even if you can't.) Object orientation in Perlis completely orthogonal to data structure.</p><p><a name="INDEX-2410"></a><a name="INDEX-2411"></a>Once the referent has been blessed, calling the built-in <tt class="literal">ref</tt> functionon its reference returns the name of the blessed class instead of the built-in type, such as <tt class="literal">HASH</tt>. If you wantthe built-in type, use the <tt class="literal">reftype</tt> function from the <tt class="literal">attributes</tt>module. See <tt class="literal">use attributes</tt> in <a href="ch31_01.htm">Chapter 31, "Pragmatic Modules"</a>.</p><p><a name="INDEX-2412"></a><a name="INDEX-2413"></a><a name="INDEX-2414"></a>And that's how to make an object. Just take a reference to something,give it a class by blessing it into a package, and you're done. That'sall there is to it if you're designing a minimal class. If you're using aclass, there's even less to it, because the author of a class will havehidden the <tt class="literal">bless</tt> inside a method called a <em class="emphasis">constructor</em>, whichcreates and returns instances of the class. Because <tt class="literal">bless</tt> returnsits first argument, a typical constructor can be as simple as this:<blockquote><pre class="programlisting">package Critter;sub spawn { bless {}; }</pre></blockquote>Or, spelled out slightly more explicitly:<blockquote><pre class="programlisting">package Critter;sub spawn { my $self = {}; # Reference to an empty anonymous hash bless $self, "Critter"; # Make that hash a Critter object return $self; # Return the freshly generated Critter}</pre></blockquote>With that definition in hand, here's how one might create a <tt class="literal">Critter</tt>object:<blockquote><pre class="programlisting">$pet = Critter->spawn;</pre></blockquote></p><h3 class="sect2">12.4.1. Inheritable Constructors</h3><p><a name="INDEX-2415"></a><a name="INDEX-2416"></a><a name="INDEX-2417"></a><a name="INDEX-2418"></a>Like all methods, a constructor is just a subroutine, but we don'tcall it as a subroutine. We always invoke it as a method--a classmethod, in this particular case, because the invocant is a packagename. Method invocations differ from regular subroutine calls in twoways. First, they get the extra argument we discussed earlier.Second, they obey inheritance, allowing one class to use another'smethods.</p><p>We'll describe the underlying mechanics of inheritance more rigorouslyin the next section, but for now, some simple examples of its effectsshould help you design your constructors. For instance, suppose wehave a <tt class="literal">Spider</tt> class that inherits methods from the <tt class="literal">Critter</tt>class. In particular, suppose the <tt class="literal">Spider</tt> class doesn't have its own<tt class="literal">spawn</tt> method. The following correspondences apply:<a name="INDEX-2419"></a><a name="INDEX-2420"></a></p><a name="method-invocation-vs-subroutine-calls"></a><table border="1"><tr><th>Method Call</th><th>Resulting Subroutine Call</th></tr><tr><td><tt class="literal">Critter->spawn()</tt></td><td><tt class="literal">Critter::spawn("Critter")</tt></td></tr><tr><td><tt class="literal">Spider->spawn()</tt></td><td><tt class="literal">Critter::spawn("Spider")</tt></td></tr></table><p>The subroutine called is the same in both cases, but the argumentdiffers. Note that our <tt class="literal">spawn</tt> constructor above completely ignoredits argument, which means our <tt class="literal">Spider</tt> object was incorrectly blessedinto class <tt class="literal">Critter</tt>. A better constructor would provide the packagename (passed in as the first argument) to <tt class="literal">bless</tt>:<blockquote><pre class="programlisting">sub spawn { my $class = shift; # Store the package name my $self = { }; bless($self, $class); # Bless the reference into that package return $self;}</pre></blockquote>Now you could use the same subroutine for both these cases:<blockquote><pre class="programlisting">$vermin = Critter->spawn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -