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

📄 ch14.htm

📁 this is a book on pearl , simple example with explanation is given here. it could be beneficial for
💻 HTM
📖 第 1 页 / 共 5 页
字号:
    print(&quot;The quantity is &quot;    . %{$pen}-&gt;{'QTY_ON_HAND'} . &quot;\n&quot;);    print(&quot;The ink color is &quot;   . %{$pen}-&gt;{'INK_COLOR'}   . &quot;\n&quot;);</PRE></BLOCKQUOTE><HR><P>This program displays:<BLOCKQUOTE><PRE>The part number is 12A-34The quantity is 34The ink color is blue</PRE></BLOCKQUOTE><P>You should be familiar with all the aspects of this script bynow. The line <TT>my($self) = Inventory_item-&gt;new(@_);</TT>is used to get a refereNCe to an anonymous hash. This hash becomesthe object for the base class.<P>To understand that calling the parent constructor creates theobject that becomes the object for the base class, you must rememberthat an object <I>is</I> the anonymous hash. Because the parentconstructor creates the anonymous hash, the base class needs arefereNCe only to that hash in order to add its own properties.This refereNCe is stored in the <TT>$self</TT>variable.<P>You may also see the variable name <TT>$this</TT>used to hold the refereNCe in some scripts. Both <TT>$self</TT>and <TT>$this</TT> are acceptablein the object-oriented world.<BR><p><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR><TD><B>Note</B></TD></TR><TR><TD><BLOCKQUOTE>I would actually prefer the variable name <TT>$data</TT> because the hash <TT><I>is</I></TT> the object; therefore, the data <TT><I>is</I></TT> the object. But sometimes, it's good to follow conventional wisdom so that others can more easily understand your programs.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><H3><A NAME="ExamplePolymorphism">Example: Polymorphism</A></H3><P><I>Polymorphism</I>, although a big word, is a simple coNCept.It means that methods defined in the base class will overridemethods defined in the parent classes. The following small exampleclarifies this coNCept:<BLOCKQUOTE><PRE>package A;    sub foo {        print(&quot;Inside A::foo\n&quot;);    }package B;    @ISA = (A);    sub foo {        print(&quot;Inside B::foo\n&quot;);    }package main;    B-&gt;foo();</PRE></BLOCKQUOTE><P>This program displays<BLOCKQUOTE><PRE>Inside B::foo</PRE></BLOCKQUOTE><P>The <TT>foo()</TT> defined in class<TT>B</TT> overrides the definitionthat was inherited from class <TT>A</TT>.<P>Polymorphism is mainly used to add or extend the fuNCtionalityof an existing class without reprogramming the whole class. Listing14.4 uses polymorphism to override the <TT>qtyChange()</TT>fuNCtion inherited from <TT>Inventory_item</TT>.In addition, it shows how to call a method in a parent class whenthe specific parent class name (also known as the <TT><I>SUPER</I></TT>class) is unknown.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Start a definition of the </I><TT><I>Inventory_item</I></TT><I>class.<BR>Define the constructor for the class.<BR>Get the name of the class from the parameter array.<BR>Assign the rest of the parameters to the </I><TT><I>%params</I></TT><I>hash.<BR>Bless the anonymous hash with the class name.<BR>Use </I><TT><I>%params</I></TT><I>to initialize the class properties.<BR>Define the </I><TT><I>qtyChange()</I></TT><I>method.<BR>Get the object refereNCe from the parameter array.<BR>Get the quantity to change from the parameter array. If thereare no more elements in the </I><TT><I>@_</I></TT><I>,default to using the quantity 1.<BR>Use derefereNCing to change the </I><TT><I>QTY_ON_HAND</I></TT><I>property.<BR>Start a definition of the </I><TT><I>Pen</I></TT><I>class.<BR>Initialize the </I><TT><I>@ISA</I></TT><I>array to define the parent classes.<BR>Initialize the </I><TT><I>@PARENT::ISA</I></TT><I>array to let Perl search the </I><TT><I>@ISA</I></TT><I>to look for method refereNCes.<BR>Define the constructor for the class.<BR>Get the name of the class from the parameter array.<BR>Assign the rest of the parameters to the </I><TT><I>%params</I></TT><I>hash.<BR>Call the constructor for the parent class using the </I><TT><I>PARENT::</I></TT><I>notation. This searches the classes listed in the </I><TT><I>@ISA</I></TT><I>array looking for the </I><TT><I>new()</I></TT><I>fuNCtion  and assigns the resulting object refereNCe to </I><TT><I>$self</I></TT><I>.<BR>Create an entry in the anonymous hash for the </I><TT><I>INK_COLOR</I></TT><I>key.<BR>Return a refereNCe to the anonymous hash.<BR>Define the </I><TT><I>qtyChange()</I></TT><I>method.<BR>Get the object refereNCe from the parameter array.<BR>Get the quantity to change from the parameter array. If thereare no more elements in the </I><TT><I>@_</I></TT><I>,default to using the quantity 100.<BR>Use derefereNCing to change the </I><TT><I>QTY_ON_HAND</I></TT><I>property.<BR>Start the </I><TT><I>main</I></TT><I>namespace.<BR>Call the constructor for the </I><TT><I>Pen</I></TT><I>class. Assign the object refereNCe to </I><TT><I>$item</I></TT><I>.<BR>Print the data type of </I><TT><I>$item</I></TT><I>to show that it is now Pen.<BR>Print the three property values to verify that the property initialization worked.<BR>Change the quantity by the default amount.<BR>Print a newline to separate the previous values from the new value.<BR>Print the quantity property value to verify that the change methodworked.</I></BLOCKQUOTE><HR><BLOCKQUOTE><B>Listing 14.4&nbsp;&nbsp;14LST04.PL-Accessing Methods in ParentClasses<BR></B></BLOCKQUOTE><BLOCKQUOTE><PRE>package Inventory_item;    sub new {        my($class)  = shift;        my(%params) = @_;        bless {            &quot;PART_NUM&quot;    =&gt; $params{&quot;PART_NUM&quot;},            &quot;QTY_ON_HAND&quot; =&gt; $params{&quot;QTY_ON_HAND&quot;}        }, $class;    }    sub qtyChange {        my($self)  = shift;        my($delta)  = $_[0] ? $_[0] : 1;        $self-&gt;{&quot;QTY_ON_HAND&quot;} += $delta;    }package Pen;    @ISA = (&quot;Inventory_item&quot;);    @PARENT::ISA = @ISA;    sub new {        my($class) = shift;        my(%params) = @_;        my($self) = $class-&gt;PARENT::new(@_);        $self-&gt;{&quot;INK_COLOR&quot;} = $params{&quot;INK_COLOR&quot;};        return($self);    }    sub qtyChange {        my($self)  = shift;        my($delta)  = $_[0] ? $_[0] : 100;        $self-&gt;PARENT::qtyChange($delta);    }    package main;    $pen = Pen-&gt;new(        &quot;PART_NUM&quot;=&gt;&quot;12A-34&quot;,        &quot;QTY_ON_HAND&quot;=&gt;340,        &quot;INK_COLOR&quot; =&gt; &quot;blue&quot;);    print(&quot;The data type is &quot;   . ref($pen)                . &quot;\n&quot;);    print(&quot;The part number is &quot; . %{$pen}-&gt;{'PART_NUM'}    . &quot;\n&quot;);    print(&quot;The quantity is &quot;    . %{$pen}-&gt;{'QTY_ON_HAND'} . &quot;\n&quot;);    print(&quot;The ink color is &quot;   . %{$pen}-&gt;{'INK_COLOR'}   . &quot;\n&quot;);    $pen-&gt;qtyChange();    print(&quot;\n&quot;);    print(&quot;The quantity is &quot;    . %{$pen}-&gt;{'QTY_ON_HAND'} . &quot;\n&quot;);</PRE></BLOCKQUOTE><HR><P>This program displays<BLOCKQUOTE><PRE>The data type is PenThe part number is 12A-34The quantity is 340The ink color is blueThe quantity is 440</PRE></BLOCKQUOTE><P>The first interesting line in the preceding example is <TT>my($delta) = $_[0] ? $_[0] : 1;</TT>. This line checks to see ifa parameter was passed to <TT>Inventory_item::qtychange()</TT>and if not, assigns a value of 1 to <TT>$delta</TT>.This line of code uses the <TT>ternary</TT>operator to determine if <TT>$_[0]</TT>has a value or not. A zero is used as the subscript because theclass refereNCe was shifted out of the parameter array and into<TT>$self</TT>.<P>The next interesting line is <TT>@PARENT::ISA= @ISA;</TT>. This assignment lets you refer to a methoddefined in the parent class. Perl searches the parent hierarchy(the <TT>@ISA</TT> array) until adefinition is found for the requested fuNCtion.<P>The <TT>Pen::new()</TT> fuNCtion usesthe <TT>@PARENT::ISA</TT> to findthe parent constructor using this line: <TT>my($self)= $class-&gt;PARENT::new(@_);</TT>. I don't really recommendcalling parent constructors in this manner because the constructorthat gets called will depend on the order of classes in the <TT>@ISA</TT>array. Having code that is dependent on an array keeping a specificorder is a recipe for disaster; you might forget about the dependeNCyand spend hours trying to find the problem. However, I thoughtyou should see how it works. Because the <TT>$class</TT>variable (which is equal to <TT>Pen</TT>)is used to locate the parent constructor, the hash will be blessedwith the name of the base <TT>Pen</TT>class-one small advantage of this technique. This is shown bythe program's output. This technique avoids having to call the<TT>bless()</TT> fuNCtion in the baseclass constructor.<P>By now, you must be wondering where polymorphism fits into thisexample. Well, the simple fact that both the <TT>Pen</TT>and <TT>Inventory_item</TT> classeshave the <TT>qtyChange()</TT> methodmeans that polymorphism is being used. While the <TT>Inventory_item::qtyChange()</TT>method defaults to changing the quantity by one, the <TT>Pen::qtyChange()</TT>method defaults to changing the quantity by 100. Because the <TT>Pen::qtyChange()</TT>method simply modifies the behavior of <TT>Inventory_item::qtyChange()</TT>,it does not need to know any details about how the quantity isactually changed. This capability to change fuNCtionality withoutknowing the details is a sign that abstraction is taking place.<BR><p><CENTER><TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%><TR><TD><B>Tip</B></TD></TR><TR><TD><BLOCKQUOTE>The <TT>Inventory_item::qtychange()</TT> notation refers to the <TT>qtyChange()</TT> fuNCtion in the <TT>Inventory_item</TT> class, and <TT>Pen::qtyChange()</TT> refers to the <TT>qtyChange()</TT> fuNCtion in the <TT>Pen</TT> class. This notation lets you uniquely identify any method in your script.</BLOCKQUOTE></TD></TR></TABLE></CENTER><P><H3><A NAME="ExampleHowOneClassCanContainAnother">Example: How One Class Can Contain Another</A></H3><P>Now that you have seen several objects in action, you probablyrealize that some class properties will be objects themselves.For example, you might have a billing object that contains aninventory object, or you might use a car object inside a warehouseobject. The possibilities are endless.<P>Listing 14.5 shows how to add a color object to the inventorysystem you've been building. It also shows you that Perl willexecute statements that are not part of a fuNCtion-even thosein packages other than main-as soon as they are seen by the interpreter.<P><IMG SRC="pseudo.gif" BORDER=1 ALIGN=RIGHT><p><BLOCKQUOTE><I>Start a definition of the </I><TT><I>Inventory_item</I></TT><I>class.<BR>Define the constructor for the class.<BR>Get the name of the class from the parameter array.<BR>Assign the rest of the parameters to the </I><TT><I>%params</I></TT><I>hash.<BR>Bless the anonymous hash with the class name.<BR>Use </I><TT><I>%params</I></TT><I>to initialize the class properties.<BR>Start a definition of the </I><TT><I>Pen</I></TT><I>class.<BR>Initialize the </I><TT><I>@ISA</I></TT><I>array to define the parent classes.<BR>Define the constructor for the class.<BR>Get the name of the class from the parameter array.<BR>Assign the rest of the parameters to the </I><TT><I>%params</I></TT><I>hash.<BR>Call the constructor for the parent class and assign the resultingobject refereNCe to </I><TT><I>$self</I></TT><I>.<BR>Create an entry in the anonymous hash for the </I><TT><I>INK_COLOR</I></TT><I>key by calling the constructor for the </I><TT><I>Color</I></TT><I>class.<BR>Return a refereNCe to the anonymous hash that has been blessedinto the </I><TT><I>Pen</I></TT><I>class.<BR>Start a definition of the </I><TT><I>Color</I></TT><I>class.<BR>Print a message on </I><TT><I>STDOUT</I></TT><I>.<BR>Create two entries in the </I><TT><I>%Colors</I></TT><I>hash.<BR>Define the constructor for the class.<BR>

⌨️ 快捷键说明

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