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

📄 ch14.htm

📁 prrl 5 programs codes in the book
💻 HTM
📖 第 1 页 / 共 5 页
字号:
errors. For example, if pens were sold in lots of 100, the <TT>changeQuantityOnHand()</TT>

fuNCtion would reflect this. Changing the quantity by only one

would not be possible. This enforcement of business rules is one

of the biggest attractions of object-oriented programming.

<H2><A NAME="HowPerlHandlesObjects"><FONT SIZE=5 COLOR=#FF0000>

How Perl Handles Objects</FONT></A></H2>

<P>

Remember the coNCept of refereNCes that was discussed in <A HREF="ch8.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch8.htm">Chapter

8</a>, &quot;RefereNCes&quot;?  If not, please re-read it. RefereNCes

will play a large role in the rest of the chapter and are critical

to understanding how classes are used. You specifically need to

remember that the <TT>{ }</TT> notation

indicates an anonymous hash. Armed with this knowledge and the

object-oriented terminology from the first part of this chapter,

you are ready to look at real Perl objects. Listing 14.1 shows

you how the <TT>inventory_item</TT>

class could be defined in Perl.

<P>

<IMG SRC="pseudo.gif" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/pseudo.gif" BORDER=1 ALIGN=RIGHT><p>

<BLOCKQUOTE>

<I>Start a new class called </I><TT><I>Inventory_item</I></TT><I>.

The </I><TT><I>package</I></TT><I>

keyword is used to introduce new classes and namespaces.<BR>

Define the </I><TT><I>new()</I></TT><I>

fuNCtion. This fuNCtion is responsible for constructing a new

object.<BR>

The first parameter to the </I><TT><I>new()</I></TT><I>

fuNCtion is the class name (</I><TT><I>Inventory_item</I></TT><I>).

This is explained further in the sections &quot;Example: Initializing

Object Properties&quot; and &quot;Static Versus Regular Methods&quot;

later in the chapter.<BR>

The </I><TT><I>bless()</I></TT><I>

fuNCtion is used to change the data type of the anonymous hash

to </I><TT><I>$class</I></TT><I> or

</I><TT><I>Inventory_item</I></TT><I>.

Because this is the last statement in the method, its value will

be returned as the value of the fuNCtion. I feel that using the

return statement to explicitly return a value would clutter the

code in this situation.<BR>

An anonymous hash is used to hold the properties for the class.

For the moment, their values are undefined. Assigning values to

properties is discussed in the section &quot;Example: Initializing

Properties&quot; later in this chapter.<BR>

Switch to the package called </I><TT><I>main</I></TT><I>.

This is the default place for variables and code to go (technically,

this is called a namespace). If no classes are defined in your

script, then this line is not needed.<BR>

Assign an instaNCe of the </I><TT><I>Inventory_item</I></TT><I>

class to the </I><TT><I>$item variable</I></TT><I>.</I>

</BLOCKQUOTE>

<HR>

<BLOCKQUOTE>

<B>Listing 14.1&nbsp;&nbsp;14LST01.PL-Defining the </B><TT><B><FONT FACE="Courier">Inventory_item</FONT></B></TT><B>

Class<BR>

</B>

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

package Inventory_item;

    sub new {

        my($class) = shift;

    

        bless {

            &quot;PART_NUM&quot;    =&gt; undef,

            &quot;QTY_ON_HAND&quot; =&gt; undef

        }, $class;

    }



package main;

   $item = Inventory_item-&gt;new();

</PRE>

</BLOCKQUOTE>

<HR>

<P>

There is a <I>lot</I> of new stuff in this small ten-line listing,

and you'll need to review it carefully to glean the information

needed to understand everything that is happening. You'll also

start to translate between the Perl keywords and the object-oriented

terminology.

<P>

The first line, <TT>package Inventory_item</TT>;

says two things, depending on if you are thinking in terms of

objects or in terms of Perl. When considering objects, it begins

the definition of a class. When considering Perl, it means that

a specific namespace will be used.

<P>

You read a little bit about namespace in <A HREF="ch3.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch3.htm" >Chapter 3</A> &quot;Variables.&quot;

A <I>namespace</I> is used to keep one set of names from interfering

with another. For example, you can have a variable named bar and

a fuNCtion called <TT>bar</TT>, and

the names will not conflict because variables and fuNCtions each

have their own namespace.

<P>

The <TT>package</TT> keyword lets

you create your own namespace. This lets you create more than

one fuNCtion called <TT>new()</TT>

as long as each is in its own package or namespace. If you need

to refer to a specific fuNCtion in a specific namespace, you can

use <TT>Inventory_item&#173;&gt;new</TT>,

<TT>Inventory_item::new</TT>, or <TT>Inventory_item'new</TT>.

Which notation you use will probably depend on your background.

Object-oriented folks will probably want to use the -&gt; notation.

<P>

The second line, <TT>sub new</TT>,

starts the definition of a fuNCtion. It has become accepted practice

in the object-oriented world to construct new objects with the

<TT>new()</TT> method. This is called

the class <I>constructor</I>. This might be a good time to emphasize

that the class definition is a template. It's only when the <TT>new()</TT>

fuNCtion is called that an object is created or <I>instantiated</I>.

Instantiation means that memory is allocated from your computer's

memory pool and devoted to the use of this specific object. The

<TT>new()</TT> fuNCtion normally returns

a refereNCe to an anonymous hash. Therefore, the <TT>new()</TT>

fuNCtion should never be called unless you are assigning its return

value to a variable. If you don't store the refereNCe into a scalar

variable for later use, you'll never be able to access the anonymous

hash inside the object. For all intents and purposes, the anonymous

hash <I>is</I> the object.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Note</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

Not all objects are represented by hashes. If you need an object to emulate a gas tank, perhaps an anonymous scalar would be sufficient to hold the number of gallons of gas left in the tank. However, you'll see that working with hashes is quite easy oNCe 
you learn how. Hashes give you tremendous flexibility to solve programming problems.</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

There is nothing magic about the new fuNCtion name. You could

call the fuNCtion that creates new objects <TT>create()</TT>

or <TT>build()</TT> or anything else,

but don't. The standard is <TT>new()</TT>,

and everyone who reads your program or uses your classes will

look for a <TT>new()</TT> fuNCtion.

If they don't find one, confusion might set in. There are so few

standards in the programming business. When they exist, it's usually

a good idea to follow them.

<P>

The <TT>bless()</TT> fuNCtion on the

third line changes the data type of its first parameter to the

string value of its second parameter. In the situation shown here,

the data type is changed to the name of the package, <TT>Inventory_item</TT>.

Using <TT>bless()</TT> to change the

data type of a refereNCe causes the <TT>ref()</TT>

fuNCtion to return the new data type. This potentially confusing

point is explained further in the section &quot;Example: Bless

the Hash and Pass the RefereNCe&quot; later in this chapter.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Note</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

I used the <TT>bless()</TT> fuNCtion without using parentheses to surround the parameters. While Perl lets you do this, I have been studiously using parentheses to avoid certain issues of precedeNCe that seem beyond the scope of this book. In this special 
instaNCe, where the anonymous hash is one of the parameters, I feel that using parentheses clutters the source code.

</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

Embedded inside the <TT>bless()</TT>

fuNCtion call is the creation of an anonymous hash that holds

the properties of the class. The hash definition is repeated here

for your convenieNCe:

<BLOCKQUOTE>

<PRE>

{

    &quot;PART_NUM&quot;    =&gt; undef,

    &quot;QTY_ON_HAND&quot; =&gt; undef

};

</PRE>

</BLOCKQUOTE>

<P>

Nothing significant is happening here that you haven't seen before.

Each entry in the hash is a different property of the class. For

the moment, I have assigned the undefined value to the value part

of the entries. Soon you'll see how to properly initialize them.

<P>

After the <TT>new()</TT> fuNCtion

is defined, there is another package statement:

<BLOCKQUOTE>

<PRE>

package main;

</PRE>

</BLOCKQUOTE>

<P>

There is no object-oriented way to interpret this statement. It

simply tells Perl to switch back to using the <TT>main</TT>

namespace. Don't be fooled into thinking that there is a <TT>main</TT>

class somewhere. There isn't.<BR>

<p>

<CENTER>

<TABLE BORDERCOLOR=#000000 BORDER=1 WIDTH=80%>

<TR><TD><B>Caution</B></TD></TR>

<TR><TD>

<BLOCKQUOTE>

While you could create a <TT>main</TT> class by defining the <TT>new()</TT> fuNCtion after the <TT>package main;</TT> statement, things might get to be confusing, so don't do it!

</BLOCKQUOTE>



</TD></TR>

</TABLE>

</CENTER>

<P>

<P>

The last statement in the file is really the first line that gets

executed. Everything else in the script has been class and method

definitions.

<BLOCKQUOTE>

<PRE>

   $item = Inventory_item-&gt;new();

</PRE>

</BLOCKQUOTE>

<P>

By now, you've probably guessed what this statement does. It assigns

a refereNCe to the anonymous hash to <TT>$item</TT>.

You can derefereNCe <TT>$item</TT>

in order to determine the value of the entries in the hash. If

you use the <TT>ref()</TT> fuNCtion

to determine the data type of <TT>$item</TT>,

you find that its value is <TT>Inventory_item</TT>.

<P>

Here are some key items to remember about objects in Perl:

<BLOCKQUOTE>

<B>All objects are anonymous hashes:</B> While not strictly true,

perhaps it should be. Also, most of the examples in this book

follow this rule. This means that most of the <TT>new()</TT>

methods you see return a refereNCe to a hash.

</BLOCKQUOTE>

<BLOCKQUOTE>

<TT><B><FONT FACE="Courier">bless()</FONT></B></TT><B> changes

the data type of the anonymous hash:</B> The data type is changed

to the name of the class.

</BLOCKQUOTE>

<BLOCKQUOTE>

<B>The anonymous hash itself is blessed:</B> This means that refereNCes

to the hash are not blessed. This coNCept is probably a little

uNClear. I had trouble figuring it out myself. The next section

clarifies this point and uses an example.

</BLOCKQUOTE>

<BLOCKQUOTE>

<B>Objects can belong to only one class at a time:</B> You can

use the <TT>bless()</TT> fuNCtion

to change the ownership at any time. However, don't do this unless

you have a good reason.

</BLOCKQUOTE>

<BLOCKQUOTE>

<B>The </B><TT><B><FONT FACE="Courier">-&gt;</FONT></B></TT><B>

operator is used to call a method associated with a class:</B>

There are two different ways to invoke or call class methods:

</BLOCKQUOTE>

<BLOCKQUOTE>

<PRE>

$item = new Inventory_item;

</PRE>

</BLOCKQUOTE>

<P>

or

<BLOCKQUOTE>

<PRE>

$item = Inventory_item-&gt;new();

</PRE>

</BLOCKQUOTE>

<P>

Both of these techniques are equivalent, but the <TT>-&gt;</TT>

style is preferred by object-oriented folks.

<H3><A NAME="ExampleBlesstheHashandPasstheRefereNCe">

Example: Bless the Hash and Pass the RefereNCe</A></H3>

<P>

If you recall from <A HREF="ch8.htm" tppabs="http://cheminf.nankai.edu.cn/~eb~/Perl%205%20By%20Example/ch8.htm" >Chapter 8</A> the <TT>ref()</TT>

fuNCtion returns either the undefined value or a string indicating

the parameter's data type (<TT>SCALAR</TT>,

<TT>ARRAY</TT>, <TT>HASH</TT>,

<TT>CODE</TT>, or <TT>REF</TT>).

When classes are used, these data types don't provide enough information.

<P>

This is why the <TT>bless()</TT> fuNCtion

was added to the language. It lets you change the data type of

any variable. You can change the data type to any string value

you like. Most often, the data type is changed to reflect the

class name.

<P>

It is important to understand that the variable itself will have

its data type changed. The following lines of code should make

this clear:

<BLOCKQUOTE>

<PRE>

$foo    = { };

$fooRef = $foo;



print(&quot;data of \$foo is &quot;    . ref($foo)    . &quot;\n&quot;);

print(&quot;data of \$fooRef is &quot; . ref($fooRef) . &quot;\n&quot;);



bless($foo, &quot;Bar&quot;);



print(&quot;data of \$foo is &quot;    . ref($foo)    . &quot;\n&quot;);

print(&quot;data of \$fooRef is &quot; . ref($fooRef) . &quot;\n&quot;);

</PRE>

</BLOCKQUOTE>

<P>

This program displays the following:

<BLOCKQUOTE>

<PRE>

data of $foo is HASH

data of $fooRef is HASH

data of $foo is Bar

data of $fooRef is Bar

</PRE>

</BLOCKQUOTE>

<P>

After the data type is changed, the <TT>ref($fooRef)</TT>

fuNCtion call returns <TT>Bar</TT>

instead of the old value of <TT>HASH</TT>.

This can happen only if the variable itself has been altered.

This example also shows that the <TT>bless()</TT>

⌨️ 快捷键说明

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