997 lines
35 KiB
HTML
997 lines
35 KiB
HTML
|
|
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
|
<HTML><HEAD><TITLE>Man page of HTML::Tree::AboutObjects</TITLE>
|
|
</HEAD><BODY>
|
|
<H1>HTML::Tree::AboutObjects</H1>
|
|
Section: User Contributed Perl Documentation (3pm)<BR>Updated: 2019-01-13<BR><A HREF="#index">Index</A>
|
|
<A HREF="/cgi-bin/man/man2html">Return to Main Contents</A><HR>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<A NAME="lbAB"> </A>
|
|
<H2>NAME</H2>
|
|
|
|
HTML::Tree::AboutObjects -- article: "User's View of Object-Oriented Modules"
|
|
<A NAME="lbAC"> </A>
|
|
<H2>SYNOPSIS</H2>
|
|
|
|
|
|
|
|
|
|
|
|
<PRE>
|
|
# This an article, not a module.
|
|
|
|
</PRE>
|
|
|
|
|
|
<A NAME="lbAD"> </A>
|
|
<H2>DESCRIPTION</H2>
|
|
|
|
|
|
|
|
The following article by Sean M. Burke first appeared in <I>The Perl
|
|
Journal</I> #17 and is copyright 2000 The Perl Journal. It appears
|
|
courtesy of Jon Orwant and The Perl Journal. This document may be
|
|
distributed under the same terms as Perl itself.
|
|
<A NAME="lbAE"> </A>
|
|
<H2>A User's View of Object-Oriented Modules</H2>
|
|
|
|
|
|
|
|
-- Sean M. Burke
|
|
<P>
|
|
|
|
The first time that most Perl programmers run into object-oriented
|
|
programming when they need to use a module whose interface is
|
|
object-oriented. This is often a mystifying experience, since talk of
|
|
``methods'' and ``constructors'' is unintelligible to programmers who
|
|
thought that functions and variables was all there was to worry about.
|
|
<P>
|
|
|
|
Articles and books that explain object-oriented programming (<FONT SIZE="-1">OOP</FONT>), do so
|
|
in terms of how to program that way. That's understandable, and if you
|
|
learn to write object-oriented code of your own, you'd find it easy to
|
|
use object-oriented code that others write. But this approach is the
|
|
<I>long</I> way around for people whose immediate goal is just to use
|
|
existing object-oriented modules, but who don't yet want to know all the
|
|
gory details of having to write such modules for themselves.
|
|
<P>
|
|
|
|
This article is for those programmers --- programmers who want to know
|
|
about objects from the perspective of using object-oriented modules.
|
|
<A NAME="lbAF"> </A>
|
|
<H3>Modules and Their Functional Interfaces</H3>
|
|
|
|
|
|
|
|
Modules are the main way that Perl provides for bundling up code for
|
|
later use by yourself or others. As I'm sure you can't help noticing
|
|
from reading
|
|
<I>The Perl Journal</I>, <FONT SIZE="-1">CPAN</FONT> (the Comprehensive Perl Archive
|
|
Network) is the repository for modules (or groups of modules) that
|
|
others have written, to do anything from composing music to accessing
|
|
Web pages. A good deal of those modules even come with every
|
|
installation of Perl.
|
|
<P>
|
|
|
|
One module that you may have used before, and which is fairly typical in
|
|
its interface, is Text::Wrap. It comes with Perl, so you don't even
|
|
need to install it from <FONT SIZE="-1">CPAN.</FONT> You use it in a program of yours, by
|
|
having your program code say early on:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
use Text::Wrap;
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
and after that, you can access a function called <TT>"wrap"</TT>, which inserts
|
|
line-breaks in text that you feed it, so that the text will be wrapped to
|
|
seventy-two (or however many) columns.
|
|
<P>
|
|
|
|
The way this <TT>"use Text::Wrap"</TT> business works is that the module
|
|
Text::Wrap exists as a file ``Text/Wrap.pm'' somewhere in one of your
|
|
library directories. That file contains Perl code...
|
|
|
|
|
|
<P>
|
|
|
|
|
|
<DL COMPACT><DT id="1"><DD>
|
|
Footnote: And mixed in with the Perl code, there's documentation, which
|
|
is what you read with ``perldoc Text::Wrap''. The perldoc program simply
|
|
ignores the code and formats the documentation text, whereas ``use
|
|
Text::Wrap'' loads and runs the code while ignoring the documentation.
|
|
</DL>
|
|
|
|
<P>
|
|
|
|
...which, among other things, defines a function called <TT>"Text::Wrap::wrap"</TT>,
|
|
and then <TT>"exports"</TT> that function, which means that when you say <TT>"wrap"</TT>
|
|
after having said ``use Text::Wrap'', you'll be actually calling the
|
|
<TT>"Text::Wrap::wrap"</TT> function. Some modules don't export their
|
|
functions, so you have to call them by their full name, like
|
|
<TT>"Text::Wrap::wrap(...parameters...)"</TT>.
|
|
<P>
|
|
|
|
Regardless of whether the typical module exports the functions it
|
|
provides, a module is basically just a container for chunks of code that
|
|
do useful things. The way the module allows for you to interact with
|
|
it, is its <I>interface</I>. And when, like with Text::Wrap, its interface
|
|
consists of functions, the module is said to have a <B>functional
|
|
interface</B>.
|
|
|
|
|
|
<P>
|
|
|
|
|
|
<DL COMPACT><DT id="2"><DD>
|
|
Footnote: the term ``function'' (and therefore "function<I>al</I>") has
|
|
various senses. I'm using the term here in its broadest sense, to
|
|
refer to routines --- bits of code that are called by some name and
|
|
which take parameters and return some value.
|
|
</DL>
|
|
|
|
<P>
|
|
|
|
Using modules with functional interfaces is straightforward --- instead
|
|
of defining your own ``wrap'' function with <TT>"sub wrap { ... }"</TT>, you
|
|
entrust ``use Text::Wrap'' to do that for you, along with whatever other
|
|
functions its defines and exports, according to the module's
|
|
documentation. Without too much bother, you can even write your own
|
|
modules to contain your frequently used functions; I suggest having a look at
|
|
the <TT>"perlmod"</TT> man page for more leads on doing this.
|
|
<A NAME="lbAG"> </A>
|
|
<H3>Modules with Object-Oriented Interfaces</H3>
|
|
|
|
|
|
|
|
So suppose that one day you want to write a program that will automate
|
|
the process of <TT>"ftp"</TT>ing a bunch of files from one server down to your
|
|
local machine, and then off to another server.
|
|
<P>
|
|
|
|
A quick browse through search.cpan.org turns up the module ``Net::FTP'',
|
|
which you can download and install it using normal installation
|
|
instructions (unless your sysadmin has already installed it, as many
|
|
have).
|
|
<P>
|
|
|
|
Like Text::Wrap or any other module with a familiarly functional
|
|
interface, you start off using Net::FTP in your program by saying:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
use Net::FTP;
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
However, that's where the similarity ends. The first hint of
|
|
difference is that the documentation for Net::FTP refers to it as a
|
|
<B>class</B>. A class is a kind of module, but one that has an
|
|
object-oriented interface.
|
|
<P>
|
|
|
|
Whereas modules like Text::Wrap
|
|
provide bits of useful code as <I>functions</I>, to be called like
|
|
<TT>"function(...parameters...)"</TT> or like
|
|
<TT>"PackageName::function(...parameters...)"</TT>, Net::FTP and other modules
|
|
with object-oriented interfaces provide <B>methods</B>. Methods are sort of
|
|
like functions in that they have a name and parameters; but methods
|
|
look different, and are different, because you have to call them with a
|
|
syntax that has a class name or an object as a special argument. I'll
|
|
explain the syntax for method calls, and then later explain what they
|
|
all mean.
|
|
<P>
|
|
|
|
Some methods are meant to be called as <B>class methods</B>, with the class
|
|
name (same as the module name) as a special argument. Class methods
|
|
look like this:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
ClassName->methodname(parameter1, parameter2, ...)
|
|
ClassName->methodname() # if no parameters
|
|
ClassName->methodname # same as above
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
which you will sometimes see written:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
methodname ClassName (parameter1, parameter2, ...)
|
|
methodname ClassName # if no parameters
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
Basically all class methods are for making new objects, and methods that
|
|
make objects are called "<B>constructors</B>`` (and the process of making them
|
|
is called ''constructing`` or ''instantiating``). Constructor methods
|
|
typically have the name ''new``, or something including ''new``
|
|
(''new_from_file``, etc.); but they can conceivably be named
|
|
anything --- <FONT SIZE="-1">DBI</FONT>'s constructor method is named ''connect", for example.
|
|
<P>
|
|
|
|
The object that a constructor method returns is
|
|
typically captured in a scalar variable:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$object = ClassName->new(param1, param2...);
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
Once you have an object (more later on exactly what that is), you can
|
|
use the other kind of method call syntax, the syntax for <B>object method</B>
|
|
calls. Calling object methods is just like class methods, except
|
|
that instead of the ClassName as the special argument,
|
|
you use an expression that yields an ``object''. Usually this is
|
|
just a scalar variable that you earlier captured the
|
|
output of the constructor in. Object method calls look like this:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$object->methodname(parameter1, parameter2, ...);
|
|
$object->methodname() # if no parameters
|
|
$object->methodname # same as above
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
which is occasionally written as:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
methodname $object (parameter1, parameter2, ...)
|
|
methodname $object # if no parameters
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
Examples of method calls are:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
my $session1 = Net::FTP->new("<A HREF="ftp://ftp.myhost.com">ftp.myhost.com</A>");
|
|
# Calls a class method "new", from class Net::FTP,
|
|
# with the single parameter "<A HREF="ftp://ftp.myhost.com">ftp.myhost.com</A>",
|
|
# and saves the return value (which is, as usual,
|
|
# an object), in $session1.
|
|
# Could also be written:
|
|
# new Net::FTP('<A HREF="ftp://ftp.myhost.com">ftp.myhost.com</A>')
|
|
$session1->login("sburke","aoeuaoeu")
|
|
|| die "failed to login!\n";
|
|
# calling the object method "login"
|
|
print "Dir:\n", $session1->dir(), "\n";
|
|
$session1->quit;
|
|
# same as $session1->quit()
|
|
print "Done\n";
|
|
exit;
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
Incidentally, I suggest always using the syntaxes with parentheses and
|
|
``->'' in them,
|
|
|
|
|
|
<P>
|
|
|
|
|
|
<DL COMPACT><DT id="3"><DD>
|
|
Footnote: the character-pair ``->'' is supposed to look like an
|
|
arrow, not ``negative greater-than''!
|
|
</DL>
|
|
|
|
<P>
|
|
|
|
and avoiding the syntaxes that start out ``methodname <TT>$object</TT>'' or
|
|
``methodname ModuleName''. When everything's going right, they all mean
|
|
the same thing as the ``->'' variants, but the syntax with ``->'' is more
|
|
visually distinct from function calls, as well as being immune to some
|
|
kinds of rare but puzzling ambiguities that can arise when you're trying
|
|
to call methods that have the same name as subroutines you've defined.
|
|
<P>
|
|
|
|
But, syntactic alternatives aside, all this talk of constructing objects
|
|
and object methods begs the question --- what <I>is</I> an object? There are
|
|
several angles to this question that the rest of this article will
|
|
answer in turn: what can you do with objects? what's in an object?
|
|
what's an object value? and why do some modules use objects at all?
|
|
<A NAME="lbAH"> </A>
|
|
<H3>What Can You Do with Objects?</H3>
|
|
|
|
|
|
|
|
You've seen that you can make objects, and call object methods with
|
|
them. But what are object methods for? The answer depends on the class:
|
|
<P>
|
|
|
|
A Net::FTP object represents a session between your computer and an <FONT SIZE="-1">FTP</FONT>
|
|
server. So the methods you call on a Net::FTP object are for doing
|
|
whatever you'd need to do across an <FONT SIZE="-1">FTP</FONT> connection. You make the
|
|
session and log in:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
my $session = Net::FTP->new('<A HREF="ftp://ftp.aol.com">ftp.aol.com</A>');
|
|
die "Couldn't connect!" unless defined $session;
|
|
# The class method call to "new" will return
|
|
# the new object if it goes OK, otherwise it
|
|
# will return undef.
|
|
|
|
$session->login('sburke', 'p@ssw3rD')
|
|
|| die "Did I change my password again?";
|
|
# The object method "login" will give a true
|
|
# return value if actually logs in, otherwise
|
|
# it'll return false.
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
You can use the session object to change directory on that session:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$session->cwd("/home/sburke/public_html")
|
|
|| die "Hey, that was REALLY supposed to work!";
|
|
# if the cwd fails, it'll return false
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
...get files from the machine at the other end of the session...
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
foreach my $f ('log_report_ua.txt', 'log_report_dom.txt',
|
|
'log_report_browsers.txt')
|
|
{
|
|
$session->get($f) || warn "Getting $f failed!"
|
|
};
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
...and plenty else, ending finally with closing the connection:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$session->quit();
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
In short, object methods are for doing things related to (or with)
|
|
whatever the object represents. For <FONT SIZE="-1">FTP</FONT> sessions, it's about sending
|
|
commands to the server at the other end of the connection, and that's
|
|
about it --- there, methods are for doing something to the world outside
|
|
the object, and the objects is just something that specifies what bit
|
|
of the world (well, what <FONT SIZE="-1">FTP</FONT> session) to act upon.
|
|
<P>
|
|
|
|
With most other classes, however, the object itself stores some kind of
|
|
information, and it typically makes no sense to do things with such an
|
|
object without considering the data that's in the object.
|
|
<A NAME="lbAI"> </A>
|
|
<H3>What's <I>in</I> an Object?</H3>
|
|
|
|
|
|
|
|
An object is (with rare exceptions) a data structure containing a
|
|
bunch of attributes, each of which has a value, as well as a name
|
|
that you use when you
|
|
read or set the attribute's value. Some of the object's attributes are
|
|
private, meaning you'll never see them documented because they're not
|
|
for you to read or write; but most of the object's documented attributes
|
|
are at least readable, and usually writeable, by you. Net::FTP objects
|
|
are a bit thin on attributes, so we'll use objects from the class
|
|
Business::US_Amort for this example. Business::US_Amort is a very
|
|
simple class (available from <FONT SIZE="-1">CPAN</FONT>) that I wrote for making calculations
|
|
to do with loans (specifically, amortization, using US-style
|
|
algorithms).
|
|
<P>
|
|
|
|
An object of the class Business::US_Amort represents a loan with
|
|
particular parameters, i.e., attributes. The most basic attributes of a
|
|
``loan object'' are its interest rate, its principal (how much money it's
|
|
for), and it's term (how long it'll take to repay). You need to set
|
|
these attributes before anything else can be done with the object. The
|
|
way to get at those attributes for loan objects is just like the
|
|
way to get at attributes for any class's objects: through accessors.
|
|
An <B>accessor</B> is simply any method that accesses (whether reading or
|
|
writing, <FONT SIZE="-1">AKA</FONT> getting or putting) some attribute in the given object.
|
|
Moreover, accessors are the <B>only</B> way that you can change
|
|
an object's attributes. (If a module's documentation wants you to
|
|
know about any other way, it'll tell you.)
|
|
<P>
|
|
|
|
Usually, for simplicity's sake, an accessor is named after the attribute
|
|
it reads or writes. With Business::US_Amort objects, the accessors you
|
|
need to use first are <TT>"principal"</TT>, <TT>"interest_rate"</TT>, and <TT>"term"</TT>.
|
|
Then, with at least those attributes set, you can call the <TT>"run"</TT> method
|
|
to figure out several things about the loan. Then you can call various
|
|
accessors, like <TT>"total_paid_toward_interest"</TT>, to read the results:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
use Business::US_Amort;
|
|
my $loan = Business::US_Amort->new;
|
|
# Set the necessary attributes:
|
|
$loan->principal(123654);
|
|
$loan->interest_rate(9.25);
|
|
$loan->term(20); # twenty years
|
|
|
|
# NOW we know enough to calculate:
|
|
$loan->run;
|
|
|
|
# And see what came of that:
|
|
print
|
|
"Total paid toward interest: A WHOPPING ",
|
|
$loan->total_paid_interest, "!!\n";
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
This illustrates a convention that's common with accessors: calling the
|
|
accessor with no arguments (as with <TT>$loan</TT>->total_paid_interest) usually
|
|
means to read the value of that attribute, but providing a value (as
|
|
with <TT>$loan</TT>->term(20)) means you want that attribute to be set to that
|
|
value. This stands to reason: why would you be providing a value, if
|
|
not to set the attribute to that value?
|
|
<P>
|
|
|
|
Although a loan's term, principal, and interest rates are all single
|
|
numeric values, an objects values can any kind of scalar, or an array,
|
|
or even a hash. Moreover, an attribute's value(s) can be objects
|
|
themselves. For example, consider <FONT SIZE="-1">MIDI</FONT> files (as I wrote about in
|
|
TPJ#13): a <FONT SIZE="-1">MIDI</FONT> file usually consists of several tracks. A <FONT SIZE="-1">MIDI</FONT> file is
|
|
complex enough to merit being an object with attributes like its overall
|
|
tempo, the file-format variant it's in, and the list of instrument
|
|
tracks in the file. But tracks themselves are complex enough to be
|
|
objects too, with attributes like their track-type, a list of <FONT SIZE="-1">MIDI</FONT>
|
|
commands if they're a <FONT SIZE="-1">MIDI</FONT> track, or raw data if they're not. So I
|
|
ended up writing the <FONT SIZE="-1">MIDI</FONT> modules so that the ``tracks'' attribute of a
|
|
MIDI::Opus object is an array of objects from the class MIDI::Track.
|
|
This may seem like a runaround --- you ask what's in one object, and get
|
|
<I>another</I> object, or several! But in this case, it exactly reflects
|
|
what the module is for --- <FONT SIZE="-1">MIDI</FONT> files contain <FONT SIZE="-1">MIDI</FONT> tracks, which then
|
|
contain data.
|
|
<A NAME="lbAJ"> </A>
|
|
<H3>What is an Object Value?</H3>
|
|
|
|
|
|
|
|
When you call a constructor like Net::FTP->new(<I>hostname</I>), you get
|
|
back an object value, a value you can later use, in combination with a
|
|
method name, to call object methods.
|
|
<P>
|
|
|
|
Now, so far we've been pretending, in the above examples, that the
|
|
variables <TT>$session</TT> or <TT>$loan</TT> <I>are</I> the objects you're dealing with.
|
|
This idea is innocuous up to a point, but it's really a misconception
|
|
that will, at best, limit you in what you know how to do. The reality
|
|
is not that the variables <TT>$session</TT> or <TT>$query</TT> are objects; it's a little
|
|
more indirect --- they <I>hold</I> values that symbolize objects. The kind of
|
|
value that <TT>$session</TT> or <TT>$query</TT> hold is what I'm calling an object value.
|
|
<P>
|
|
|
|
To understand what kind of value this is, first think about the other
|
|
kinds of scalar values you know about: The first two scalar values you
|
|
probably ever ran into in Perl are <B>numbers</B> and <B>strings</B>, which you
|
|
learned (or just assumed) will usually turn into each other on demand;
|
|
that is, the three-character string ``2.5'' can become the quantity two
|
|
and a half, and vice versa. Then, especially if you started using
|
|
<TT>"perl -w"</TT> early on, you learned about the <B>undefined value</B>, which can
|
|
turn into 0 if you treat it as a number, or the empty-string if you
|
|
treat it as a string.
|
|
|
|
|
|
<P>
|
|
|
|
|
|
<DL COMPACT><DT id="4"><DD>
|
|
Footnote: You may <I>also</I> have been learning about references, in which
|
|
case you're ready to hear that object values are just a kind of
|
|
reference, except that they reflect the class that created thing they point
|
|
to, instead of merely being a plain old array reference, hash reference,
|
|
etc. <I>If</I> this makes makes sense to you, and you want to know more
|
|
about how objects are implemented in Perl, have a look at the
|
|
<TT>"perltoot"</TT> man page.
|
|
</DL>
|
|
|
|
<P>
|
|
|
|
And now you're learning about <B>object values</B>. An object value is a
|
|
value that points to a data structure somewhere in memory, which is
|
|
where all the attributes for this object are stored. That data
|
|
structure as a whole belongs to a class (probably the one you named in
|
|
the constructor method, like ClassName->new), so that the object value
|
|
can be used as part of object method calls.
|
|
<P>
|
|
|
|
If you want to actually <I>see</I> what an object value is, you might try
|
|
just saying ``print <TT>$object</TT>''. That'll get you something like this:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
Net::FTP=GLOB(0x20154240)
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
or
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
Business::US_Amort=HASH(0x15424020)
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
That's not very helpful if you wanted to really get at the object's
|
|
insides, but that's because the object value is only a symbol for the
|
|
object. This may all sound very abstruse and metaphysical, so a
|
|
real-world allegory might be very helpful:
|
|
|
|
|
|
<P>
|
|
|
|
|
|
<DL COMPACT><DT id="5"><DD>
|
|
You get an advertisement in the mail saying that you have been
|
|
(im)personally selected to have the rare privilege of applying for a
|
|
credit card. For whatever reason, <I>this</I> offer sounds good to you, so you
|
|
fill out the form and mail it back to the credit card company. They
|
|
gleefully approve the application and create your account, and send you
|
|
a card with a number on it.
|
|
|
|
|
|
<P>
|
|
|
|
|
|
Now, you can do things with the number on that card --- clerks at stores
|
|
can ring up things you want to buy, and charge your account by keying in
|
|
the number on the card. You can pay for things you order online by
|
|
punching in the card number as part of your online order. You can pay
|
|
off part of the account by sending the credit card people some of your
|
|
money (well, a check) with some note (usually the pre-printed slip)
|
|
that has the card number for the account you want to pay toward. And you
|
|
should be able to call the credit card company's computer and ask it
|
|
things about the card, like its balance, its credit limit, its <FONT SIZE="-1">APR,</FONT> and
|
|
maybe an itemization of recent purchases ad payments.
|
|
|
|
|
|
<P>
|
|
|
|
|
|
Now, what you're <I>really</I> doing is manipulating a credit card
|
|
<I>account</I>, a completely abstract entity with some data attached to it
|
|
(balance, <FONT SIZE="-1">APR,</FONT> etc). But for ease of access, you have a credit card
|
|
<I>number</I> that is a symbol for that account. Now, that symbol is just a
|
|
bunch of digits, and the number is effectively meaningless and useless
|
|
in and of itself --- but in the appropriate context, it's understood to
|
|
<I>mean</I> the credit card account you're accessing.
|
|
</DL>
|
|
|
|
<P>
|
|
|
|
This is exactly the relationship between objects and object values, and
|
|
from this analogy, several facts about object values are a bit more
|
|
explicable:
|
|
<P>
|
|
|
|
* An object value does nothing in and of itself, but it's useful when
|
|
you use it in the context of an <TT>$object</TT>->method call, the same way that
|
|
a card number is useful in the context of some operation dealing with a
|
|
card account.
|
|
<P>
|
|
|
|
Moreover, several copies of the same object value all refer to the same
|
|
object, the same way that making several copies of your card number
|
|
won't change the fact that they all still refer to the same single
|
|
account (this is true whether you're ``copying'' the number by just
|
|
writing it down on different slips of paper, or whether you go to the
|
|
trouble of forging exact replicas of your own plastic credit card). That's
|
|
why this:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$x = Net::FTP->new("<A HREF="ftp://ftp.aol.com">ftp.aol.com</A>");
|
|
$x->login("sburke", "aoeuaoeu");
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
does the same thing as this:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$x = Net::FTP->new("<A HREF="ftp://ftp.aol.com">ftp.aol.com</A>");
|
|
$y = $x;
|
|
$z = $y;
|
|
$z->login("sburke", "aoeuaoeu");
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
That is, <TT>$z</TT> and <TT>$y</TT> and <TT>$x</TT> are three different <I>slots</I> for values,
|
|
but what's in those slots are all object values pointing to the same
|
|
object --- you don't have three different <FONT SIZE="-1">FTP</FONT> connections, just three
|
|
variables with values pointing to the some single <FONT SIZE="-1">FTP</FONT> connection.
|
|
<P>
|
|
|
|
* You can't tell much of anything about the object just by looking at
|
|
the object value, any more than you can see your credit account balance
|
|
by holding the plastic card up to the light, or by adding up the digits
|
|
in your credit card number.
|
|
<P>
|
|
|
|
* You can't just make up your own object values and have them work ---
|
|
they can come only from constructor methods of the appropriate class.
|
|
Similarly, you get a credit card number <I>only</I> by having a bank approve
|
|
your application for a credit card account --- at which point <I>they</I>
|
|
let <I>you</I> know what the number of your new card is.
|
|
<P>
|
|
|
|
Now, there's even more to the fact that you can't just make up your own
|
|
object value: even though you can print an object value and get a string
|
|
like ``Net::FTP=GLOB(0x20154240)'', that string is just a
|
|
<I>representation</I> of an object value.
|
|
<P>
|
|
|
|
Internally, an object value has a basically different type from a
|
|
string, or a number, or the undefined value --- if <TT>$x</TT> holds a real
|
|
string, then that value's slot in memory says "this is a value of type
|
|
<I>string</I>, and its characters are...``, whereas if it's an object value,
|
|
the value's slot in memory says, ''this is a value of type <I>reference</I>,
|
|
and the location in memory that it points to is..." (and by looking at
|
|
what's at that location, Perl can tell the class of what's there).
|
|
<P>
|
|
|
|
Perl programmers typically don't have to think about all these details
|
|
of Perl's internals. Many other languages force you to be more
|
|
conscious of the differences between all of these (and also between
|
|
types of numbers, which are stored differently depending on their size
|
|
and whether they have fractional parts). But Perl does its best to
|
|
hide the different types of scalars from you --- it turns numbers into
|
|
strings and back as needed, and takes the string or number
|
|
representation of undef or of object values as needed. However, you
|
|
can't go from a string representation of an object value, back to an
|
|
object value. And that's why this doesn't work:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
$x = Net::FTP->new('<A HREF="ftp://ftp.aol.com">ftp.aol.com</A>');
|
|
$y = Net::FTP->new('<A HREF="ftp://ftp.netcom.com">ftp.netcom.com</A>');
|
|
$z = Net::FTP->new('<A HREF="ftp://ftp.qualcomm.com">ftp.qualcomm.com</A>');
|
|
$all = join(' ', $x,$y,$z); # !!!
|
|
...later...
|
|
($aol, $netcom, $qualcomm) = split(' ', $all); # !!!
|
|
$aol->login("sburke", "aoeuaoeu");
|
|
$netcom->login("sburke", "qjkxqjkx");
|
|
$qualcomm->login("smb", "dhtndhtn");
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
This fails because <TT>$aol</TT> ends up holding merely the <B>string representation</B>
|
|
of the object value from <TT>$x</TT>, not the object value itself --- when
|
|
<TT>"join"</TT> tried to join the characters of the ``strings'' <TT>$x</TT>, <TT>$y</TT>, and <TT>$z</TT>,
|
|
Perl saw that they weren't strings at all, so it gave <TT>"join"</TT> their
|
|
string representations.
|
|
<P>
|
|
|
|
Unfortunately, this distinction between object values and their string
|
|
representations doesn't really fit into the analogy of credit card
|
|
numbers, because credit card numbers really <I>are</I> numbers --- even
|
|
thought they don't express any meaningful quantity, if you stored them
|
|
in a database as a quantity (as opposed to just an <FONT SIZE="-1">ASCII</FONT> string),
|
|
that wouldn't stop them from being valid as credit card numbers.
|
|
<P>
|
|
|
|
This may seem rather academic, but there's there's two common mistakes
|
|
programmers new to objects often make, which make sense only in terms of
|
|
the distinction between object values and their string representations:
|
|
<P>
|
|
|
|
The first common error involves forgetting (or never having known in the
|
|
first place) that when you go to use a value as a hash key, Perl uses
|
|
the string representation of that value. When you want to use the
|
|
numeric value two and a half as a key, Perl turns it into the
|
|
three-character string ``2.5''. But if you then want to use that string
|
|
as a number, Perl will treat it as meaning two and a half, so you're
|
|
usually none the wiser that Perl converted the number to a string and
|
|
back. But recall that Perl can't turn strings back into objects --- so
|
|
if you tried to use a Net::FTP object value as a hash key, Perl actually
|
|
used its string representation, like ``Net::FTP=GLOB(0x20154240)'', but
|
|
that string is unusable as an object value. (Incidentally, there's
|
|
a module Tie::RefHash that implements hashes that <I>do</I> let you use
|
|
real object-values as keys.)
|
|
<P>
|
|
|
|
The second common error with object values is in
|
|
trying to save an object value to disk (whether printing it to a
|
|
file, or storing it in a conventional database file). All you'll get is the
|
|
string, which will be useless.
|
|
<P>
|
|
|
|
When you want to save an object and restore it later, you may find that
|
|
the object's class already provides a method specifically for this. For
|
|
example, MIDI::Opus provides methods for writing an object to disk as a
|
|
standard <FONT SIZE="-1">MIDI</FONT> file. The file can later be read back into memory by
|
|
a MIDI::Opus constructor method, which will return a new MIDI::Opus
|
|
object representing whatever file you tell it to read into memory.
|
|
Similar methods are available with, for example, classes that
|
|
manipulate graphic images and can save them to files, which can be read
|
|
back later.
|
|
<P>
|
|
|
|
But some classes, like Business::US_Amort, provide no such methods for
|
|
storing an object in a file. When this is the case, you can try
|
|
using any of the Data::Dumper, Storable, or FreezeThaw modules. Using
|
|
these will be unproblematic for objects of most classes, but it may run
|
|
into limitations with others. For example, a Business::US_Amort
|
|
object can be turned into a string with Data::Dumper, and that string
|
|
written to a file. When it's restored later, its attributes will be
|
|
accessible as normal. But in the unlikely case that the loan object was
|
|
saved in mid-calculation, the calculation may not be resumable. This is
|
|
because of the way that that <I>particular</I> class does its calculations,
|
|
but similar limitations may occur with objects from other classes.
|
|
<P>
|
|
|
|
But often, even <I>wanting</I> to save an object is basically wrong --- what would
|
|
saving an ftp <I>session</I> even mean? Saving the hostname, username, and
|
|
password? current directory on both machines? the local <FONT SIZE="-1">TCP/IP</FONT> port
|
|
number? In the case of ``saving'' a Net::FTP object, you're better off
|
|
just saving whatever details you actually need for your own purposes,
|
|
so that you can make a new object later and just set those values for it.
|
|
<A NAME="lbAK"> </A>
|
|
<H3>So Why Do Some Modules Use Objects?</H3>
|
|
|
|
|
|
|
|
All these details of using objects are definitely enough to make you
|
|
wonder --- is it worth the bother? If you're a module author, writing
|
|
your module with an object-oriented interface restricts the audience of
|
|
potential users to those who understand the basic concepts of objects
|
|
and object values, as well as Perl's syntax for calling methods. Why
|
|
complicate things by having an object-oriented interface?
|
|
<P>
|
|
|
|
A somewhat esoteric answer is that a module has an object-oriented
|
|
interface because the module's insides are written in an
|
|
object-oriented style. This article is about the basics of
|
|
object-oriented <I>interfaces</I>, and it'd be going far afield to explain
|
|
what object-oriented <I>design</I> is. But the short story is that
|
|
object-oriented design is just one way of attacking messy problems.
|
|
It's a way that many programmers find very helpful (and which others
|
|
happen to find to be far more of a hassle than it's worth,
|
|
incidentally), and it just happens to show up for you, the module user,
|
|
as merely the style of interface.
|
|
<P>
|
|
|
|
But a simpler answer is that a functional interface is sometimes a
|
|
hindrance, because it limits the number of things you can do at once ---
|
|
limiting it, in fact, to one. For many problems that some modules are
|
|
meant to solve, doing without an object-oriented interface would be like
|
|
wishing that Perl didn't use filehandles. The ideas are rather simpler
|
|
--- just imagine that Perl let you access files, but <I>only</I> one at a
|
|
time, with code like:
|
|
<P>
|
|
|
|
|
|
|
|
<PRE>
|
|
open("foo.txt") || die "Can't open foo.txt: $!";
|
|
while(readline) {
|
|
print $_ if /bar/;
|
|
}
|
|
close;
|
|
|
|
</PRE>
|
|
|
|
|
|
<P>
|
|
|
|
That hypothetical kind of Perl would be simpler, by doing without
|
|
filehandles. But you'd be out of luck if you wanted to read from
|
|
one file while reading from another, or read from two and print to a
|
|
third.
|
|
<P>
|
|
|
|
In the same way, a functional <FONT SIZE="-1">FTP</FONT> module would be fine for just
|
|
uploading files to one server at a time, but it wouldn't allow you to
|
|
easily write programs that make need to use <I>several</I> simultaneous
|
|
sessions (like ``look at server A and server B, and if A has a file
|
|
called X.dat, then download it locally and then upload it to server B ---
|
|
except if B has a file called Y.dat, in which case do it the other way
|
|
around'').
|
|
<P>
|
|
|
|
Some kinds of problems that modules solve just lend themselves to an
|
|
object-oriented interface. For those kinds of tasks, a functional
|
|
interface would be more familiar, but less powerful. Learning to use
|
|
object-oriented modules' interfaces does require becoming comfortable
|
|
with the concepts from this article. But in the end it will allow you
|
|
to use a broader range of modules and, with them, to write programs
|
|
that can do more.
|
|
<P>
|
|
|
|
<B>[end body of article]</B>
|
|
<A NAME="lbAL"> </A>
|
|
<H3>[Author Credit]</H3>
|
|
|
|
|
|
|
|
Sean M. Burke has contributed several modules to <FONT SIZE="-1">CPAN,</FONT> about half of
|
|
them object-oriented.
|
|
<P>
|
|
|
|
[The next section should be in a greybox:]
|
|
<A NAME="lbAM"> </A>
|
|
<H3>The Gory Details</H3>
|
|
|
|
|
|
|
|
For sake of clarity of explanation, I had to oversimplify some of the
|
|
facts about objects. Here's a few of the gorier details:
|
|
<P>
|
|
|
|
* Every example I gave of a constructor was a class method. But object
|
|
methods can be constructors, too, if the class was written to work that
|
|
way: <TT>$new</TT> = <TT>$old</TT>->copy, <TT>$node_y</TT> = <TT>$node_x</TT>->new_subnode, or the like.
|
|
<P>
|
|
|
|
* I've given the impression that there's two kinds of methods: object
|
|
methods and class methods. In fact, the same method can be both,
|
|
because it's not the kind of method it is, but the kind of calls it's
|
|
written to accept --- calls that pass an object, or calls that pass a
|
|
class-name.
|
|
<P>
|
|
|
|
* The term ``object value'' isn't something you'll find used much anywhere
|
|
else. It's just my shorthand for what would properly be called an
|
|
``object reference'' or ``reference to a blessed item''. In fact, people
|
|
usually say ``object'' when they properly mean a reference to that object.
|
|
<P>
|
|
|
|
* I mentioned creating objects with <I>con</I>structors, but I didn't
|
|
mention destroying them with <I>de</I>structor --- a destructor is a kind of
|
|
method that you call to tidy up the object once you're done with it, and
|
|
want it to neatly go away (close connections, delete temporary files,
|
|
free up memory, etc). But because of the way Perl handles memory,
|
|
most modules won't require the user to know about destructors.
|
|
<P>
|
|
|
|
* I said that class method syntax has to have the class name, as in
|
|
<TT>$session</TT> = <B>Net::FTP</B>->new($host). Actually, you can instead use any
|
|
expression that returns a class name: <TT>$ftp_class</TT> = 'Net::FTP'; <TT>$session</TT>
|
|
= <B></B>$ftp_class<B></B>->new($host). Moreover, instead of the method name for
|
|
object- or class-method calls, you can use a scalar holding the method
|
|
name: <TT>$foo</TT>-><B></B>$method<B></B>($host). But, in practice, these syntaxes are
|
|
rarely useful.
|
|
<P>
|
|
|
|
And finally, to learn about objects from the perspective of writing
|
|
your own classes, see the <TT>"perltoot"</TT> documentation,
|
|
or Damian Conway's exhaustive and clear book <I>Object Oriented Perl</I>
|
|
(Manning Publications 1999, <FONT SIZE="-1">ISBN 1-884777-79-1</FONT>).
|
|
<A NAME="lbAN"> </A>
|
|
<H2>BACK</H2>
|
|
|
|
|
|
|
|
Return to the HTML::Tree docs.
|
|
<P>
|
|
|
|
<HR>
|
|
<A NAME="index"> </A><H2>Index</H2>
|
|
<DL>
|
|
<DT id="6"><A HREF="#lbAB">NAME</A><DD>
|
|
<DT id="7"><A HREF="#lbAC">SYNOPSIS</A><DD>
|
|
<DT id="8"><A HREF="#lbAD">DESCRIPTION</A><DD>
|
|
<DT id="9"><A HREF="#lbAE">A User's View of Object-Oriented Modules</A><DD>
|
|
<DL>
|
|
<DT id="10"><A HREF="#lbAF">Modules and Their Functional Interfaces</A><DD>
|
|
<DT id="11"><A HREF="#lbAG">Modules with Object-Oriented Interfaces</A><DD>
|
|
<DT id="12"><A HREF="#lbAH">What Can You Do with Objects?</A><DD>
|
|
<DT id="13"><A HREF="#lbAI">What's <I>in</I> an Object?</A><DD>
|
|
<DT id="14"><A HREF="#lbAJ">What is an Object Value?</A><DD>
|
|
<DT id="15"><A HREF="#lbAK">So Why Do Some Modules Use Objects?</A><DD>
|
|
<DT id="16"><A HREF="#lbAL">[Author Credit]</A><DD>
|
|
<DT id="17"><A HREF="#lbAM">The Gory Details</A><DD>
|
|
</DL>
|
|
<DT id="18"><A HREF="#lbAN">BACK</A><DD>
|
|
</DL>
|
|
<HR>
|
|
This document was created by
|
|
<A HREF="/cgi-bin/man/man2html">man2html</A>,
|
|
using the manual pages.<BR>
|
|
Time: 00:05:45 GMT, March 31, 2021
|
|
</BODY>
|
|
</HTML>
|