[Notes to the editor (including this one!) are on lines starting with an open-bracket.] =head1 A User's View of Object-Oriented Modules Sean M. Burke 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. Articles and books that explain object-oriented programming (OOP), 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 way around for people whose immediate goal is just to use existing object-oriented code, but who don't yet want to know all the gory details of having to write such code for themselves. This article is for those programmers -- programmers who want to know about objects from the perspective of using object-oriented modules. =head2 Modules and Their Functional Interfaces 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, CPAN (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. One module that you may have used before, and which is fairly typical in its interface, is Text::Wrap. You use it in a program of yours, by having your program code say early on: use Text::Wrap; and after that, you can access a function called C, which inserts line-breaks in text you feed it, so that the text will be wrapped to seventy-two (or however many) columns. The way this C 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 [ 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. ] which, among other things, defines a function called C, and then C that function, which means that when you say C in code that also says "use Text::Wrap", you'll be actually calling the C function. Some modules don't export their functions, so you have to call them by their full name, like C. Regardless of whether the typical module exports the functions it provides, what it's basically about is containing code that does something useful. And for your ease of access, it bundles up the bits of code as functions. A module's way of bundling up what it does is called its B, and an interface that bundles up functions is called a B. [ Footnote: the term "function" (and therefore "functionI") 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. ] Using modules with functional interfaces is straightforward -- instead of defining your own "wrap" function with C, 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. You can even write your own modules to contain your own often-used functions without too much bother; I suggest having a look at the C man page for more leads on doing this. =head2 Modules with Object-Oriented Interfaces So suppose that one day you want to write a program that will automate the process of Cing a bunch of files from one server, to your local machine, and then off to another server. A quick browse thru search.cpan.org turns up the module "Net::FTP", which may already be installed with your copy of Perl. [ Is Net::FTP standard, and has it been for a while now? I'm not sure how to easily figure out the answer to the first question, much less the second. Edit as appropriate. ] If not, you can jump right in and use your local copy; otherwise you can install it using the normal install instructions. Like Text::Wrap or any other module with a familiarly functional interface, you start off using Net::FTP in your program by saying: use Net::FTP; However, that's where the similarity ends. Whereas those modules provide bits of useful code as I, to be called ilke C or like C, Net::FTP and other modules with object-oriented interfaces provide C, which are bundles of code that are kind of like functions, but which are meant to be accessed ("called") rather differently. The difference in interface is also reflected in the fact that when a module provides an object-oriented interface, you can call it a "class". Some methods are meant to be called as B, with the module (class) name as a special argument: [parameter1 etc are in italics, as are comments. Maybe put "ClassName", and later, "$object" in bold.] ClassName->methodname(parameter1, parameter2, ...) ClassName->methodname() # if no parameters ClassName->methodname # same as above which you will sometimes see written: methodname ClassName (parameter1, parameter2, ...) methodname ClassName # if no parameters Basically all class methods are for making new objects, and methods that make objects are called "constructors" (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.). The object that's the output of a constructor method is typically captured in a scalar variable: $object = ClassName->new(param1, param2...); Once you have an object (more on exactly what that is later), you can use the second kind of method call syntax, the syntax for B method calls. Calling object methods is just like class methods, except that instead of the ClassName, you use an expression holding an "object", usually just a scalar variable that you captured the output of the constructor in: $object->methodname(parameter1, parameter2, ...); $object->methodname() # if no parameters $object->methodname # same as above which is occasionally written as: methodname $object (parameter1, parameter2, ...) methodname $object # if no parameters Examples of method calls are: my $session1 = Net::FTP->new("ftp.myhost.com"); # Calls a class method "new", from class Net::FTP, # with the single parameter "ftp.myhost.com", # and saves the return value (which is, as usual, # an object), in $session1. # Could also be written: # new Net::FTP('ftp.myhost.com') $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; Incidentally, I suggest always using the syntaxes with parentheses and "->" in them, [ Footnote: the character-pair "->" is supposed to look like an arrow, not "negative greater-than"! ] and avoiding the syntaxes that start out "methodname $object" 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 subs you've defined. But, syntactic alternatives aside, all this talk of constructing objects and object methods begs the question -- what I an object? There's 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? =head2 What Can You Do with Objects? 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: An Net::FTP object represents a session between your computer and an FTP server. So the methods you call on a Net::FTP object are for doing whatever you'd need to do across an FTP connection. You make the session and log in: my $session = Net::FTP->new('ftp.aol.com'); 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. You can use the session object to change directory on that session: $session->cwd("/home/sburke/public_html") || die "Hey, that was REALLY supposed to work!"; # if the cwd fails, it'll return false ...get files from the machine at the other end of the session... foreach my $f ('log_report_ua.txt', 'log_report_dom.txt', 'log_report_browsers.txt') { $session->get($f) || warn "Getting $f failed!" }; ...and plenty else, ending finally with closing the connection: $session->quit(); In short, object methods are for doing things related to (or with) whatever the object represents. For FTP 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. 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. =head2 What's I an Object? An object is (with rare exceptions) a data structure containing a bunch of attributes, each of which has a value, and a name you 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 CGI.pm objects for example. A CGI.pm object represents practically all the circumstances surrounding a Web browser getting a Web server to call a Perl program as a CGI (typically with form data). A CGI.pm object has plenty of attributes, and the way to access them is via a special kind of object method called an B. An accessor is simply any method that accesses (whether reading or writing, AKA getting or putting) some attribute in the given object. CGI.pm's simplest accessors are ones that are read-only, and whose contents are simple scalar values to do with the invocation of the CGI program, as here: [bold remote_host and request_method here:] my $query = CGI->new(); print "Content-type: text/plain\n\n", # lame header "Hello world!\n", "The browser's hostname is apparently ", $query->remote_host(), ", doncha know!\n", "This program was accessed via a ", $query->request_method, # GET or POST, I bet! " request from the browser.\n", ; exit; A CGI.pm's most important attribute is the collection of form values passed to the CGI program, which you can think of as one big attribute, since it's accessed via a single accessor. But where the C attribute was just one scalar value, the form-values attribute contains many data values inside of it, as key-value pairs. This form-values attribute (or all its little bits) is accessed via an accessor called C. The full story can be found in the CGI.pm documentation [ or a book recommendation? Jon or Nat, can you recommend any Perl CGI books that aren't foul? Maybe Simon's new book'll have a good CGI chapter. ] , but in short, this is a good demonstration of an accessor that cleverly behaves differently depending on how you call it -- calling it with I parameters, like so: @keys = $query->param(); will return a list of strings that are all the keys from the form fields that the browser submitted. If you call C with I parameter, it considers that the name of the form field that you want the value of, and returns that: $name = $query->param('their_name'); And C is not a read-I accessor -- you can I the value of a given field, by giving it I parameters: the key name, and the value to assign: $query->param('their_name', 'Kang'); Later calls to $query->param('their_name') will return 'Kang'. In case you were wondering, the usefulness of this is that $query can be used to make HTML code that reproduces the state of some or all of the contents of C, as with this code that outputs HTML code for a form field for the field "their_name", whose contents will default to the value of $query->param('their_name'), like so: # Once you've opened sent the HTML header # and opened the form element... print "
And What's your name? ", $query->textfield('their_name'), ; Object attributes needn't be as complex as this, though. The objects of the class Business::US_Amort (a simple class that I wrote, for calculating tables representing the amortization of loans) start out with none of their attributes set, and it's up to the user to set at least some of them (like C, C, and C) before anything useful can be done. After they're set, the calculations can run, and the result can be seen in read-only attributes like C. [bolden "principal", "interest_rate", "term", and "total_paid_toward_interest", below:] use Business::US_Amort; my $loan = Business::US_Amort->new; # Set the 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"; What attributes an object can have follow directly from what the object represents. As we've seen, a "loan object"'s parameters are be all the numbers that characterize that particular loan. A CGI query object is a hazier, more sprawling concept, so it has more varied attributes, and lots of them. And it's not unheard of for the values in an object's attributes to be objects of their own. For example, consider MIDI files (as I wrote about in TPJ#13): a MIDI file usually consists of several tracks. A MIDI file is complex enough to merit being an object (of the class "MIDI::Opus"), 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 (with attributes like their track-type, a list MIDI commands if they're a MIDI track, or raw data if they're not); so I ended up writing the MIDI modules so that the "tracks" attribute of a MIDI::Opus object is a list of objects from the class MIDI::Track. This may seem like a runaround -- you ask what's in one object, and get I object! But in this case, it exactly reflects what the module is for -- MIDI files contain MIDI tracks, which contain something else. =head2 What is an Object Value? When you call a constructor like Net::FTP->new(I), you get back an object value, a value you can later use, in combination with a method name, to call object methods. Now, so far we've been pretending, in the above examples, that the variables $session or $query I the objects you're dealing with. This idea is innocuous up to a point, but it's really a misconception [ Footnote: depending on what our definitions of "are" are. ] that will, at best, limit you in what you know how to do. The reality is not that the variables $session or $query are objects; it's a little more indirect -- they I values that symbolize objects. The kind of value that $session or $query hold is what I'm calling an object value. 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 and 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 C early on, you learned about the B, which can turn into 0 if you treat it as a number, or the empty-string if you treat it as a string. [ Footnote: You may 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 of the thing they point to , instead of merely being a plain old array reference, hash reference, etc. 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 C man page. [Or instead say something to the effect of: "see the grey-box at the end of this article." Whichever you think best.] ] And now you're learning about 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. If you want to actually I what an object value is, you might try just saying "print $object". That'll get you something like this: Net::FTP=GLOB(0x20154240) 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: [maybe a little centered subsubsection heading here, "The Credit Card Metaphor"?] 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 offer sounds good, 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. 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 APR, and maybe an itemization of recent purchases ad payments. Now, what you're I doing is manipulating a credit card I, a completely abstract entity with some data attached to it (balance, APR, etc). But for ease of access, you have a credit card 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 the credit card account you're accessing. This is exactly the relationship between objects and object values, and from this analogy, several facts about object values are a bit more explicable: * An object value does nothing in and of itself, but it's useful when you use it in the context of an $object->method call, the same way that a card number is useful in the context of some operation dealing with a card account. 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 plastic credit card). That's why this: $x = Net::FTP->new("ftp.aol.com"); $x->login("sburke", "aoeuaoeu"); does the same thing as this: $x = Net::FTP->new("ftp.aol.com"); $y = $x; $z = $y; $z->login("sburke", "aoeuaoeu"); That is, $z and $y and $x are different I for values, but the value in all those slot are an object values that all point to the same single object. * 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. * 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 by having a bank approve your application for a credit card account. You can't just make up a number. 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 of object value. Internally, an object value has a basically different type from a string, or a number, or the undefined value -- if $x holds a real string, then that value's slot in memory says "this is a value of type 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, 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). 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 on 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, the concept of type becomes unavoidable here, because it's the only way to explain why this won't work: ["...later..." is in italics, and put join(...) and split(...) in bold] $x = Net::FTP->new('ftp.aol.com'); $y = Net::FTP->new('ftp.netcom.com'); $z = Net::FTP->new('ftp.qualcomm.com'); $all = join(' ', $x,$y,$z); ...later... ($aol, $netcom, $qualcomm) = split(' ', $all); $aol->login("sburke", "aoeuaoeu"); $netcom->login("sburke", "qjkxqjkx"); $qualcomm->login("smb", "dhtndhtn"); This fails because $aol ends up holding merely the B of the object value from $x, not the object value itself -- when C tried to join the characters of the "strings" $x, $y, and $z, Perl saw that they weren't strings at all, so it gave C their string representations. This is like the way that the undefined value can I like the empty-string if you try treating it as a string, but it's actually distinct from it. In fact, just as Perl provides a function, C, to tell whether or not a value's type is the undefined value (in which case C returns false) or anything else (in which case C returns true), Perl provides a function, C, to tell whether what you've got is an object value (in which case it returns the name of the object's class [ Footnote: Or, if it's a non-object Ierence, ref returns a string for the type of datum it is: C<$x = []; print ref($h)> will print "ARRAY". See the C documentation. ] ), or not (in which case it returns a false value). Now, to see the difference between a value and its string representation, consider the operation of appending an empty string to a value -- appending only makes sense for strings, so if Perl sees anything else but a string, it takes its string representation. And if you're appending nothing, you can be sure that all you end up with is the string representation of the value you put in. So: [italicize (or whatever) the commenty bits in these following sections] defined("lala") is true, of course defined("lala" . "") is still true, of course defined(undef) is false defined(undef . "") is true! Why? Because when you try appending "" (or anything else) to the undefined value, you get the string representation of the undefined value, which i a string, albeit one that has zero characters in it. ref("lala") is false, of course ref("lala" . "") is false, of course because those strings aren't object-values. But more importantly: $x = net::ftp->new('ftp.aol.com') and then: ref($x) is "net::ftp" (which is true, as a value) ref($x . "") is false! Unfortunately, this doesn't really fit into the analogy of credit card numbers, because credit card numbers really are just numbers -- even thought they don't express any meaningful quantity, if you stored them in a database as a quantity, and that wouldn't stop them from being valid as credit card numbers. This may seem rather academic, but 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: The first common error with object values is the rather elementary mistake of trying to save an object value to disk (whether printing to a file, or to a conventional database file). All you'll get is the string, which will be useless. Often even I to save an object is basically wrong -- what would saving an ftp I even mean? Saving the hostname, username, and password? current directory on both machines? the local TCP/IP port number? There you're better off just saving whatever details you actually need, so that you can make a new object later and just set those values for it. In cases where saving the object I make sense, the object's class often provides some way to get the value of the object. For an object that's a graphical image, for example, you can ask for its representation as a PNG binary object, and save that in a file as needed, and later read back in as a new object. But some classes, like Business::US_Amort, may provide methods to nicely output their contents for people to look at, but in a format that I be turned back into objects. For this case, you can try using any of the Data::Dumper, Storable, or FreezeThaw modules. Using these will be unproblematic for objects of most classes (such as MIDI::Opus objects), but it may run into limitations at 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 accessable as normal. But in the unlikely case that the loan object was saved in mid-calculation, the may not be resumable. This is because of the way that that I class does its calculations, but I mention this because one never knows if a similar problem may occur if you try to use Data::Dumper or the like to store objects from other classes. The other common error that programmers make with object values is in trying to use them as keys in a hash. This fails because of the rarely-known (or at least often-forgotten) fact that while anything can be a hash value, I. If you try to use numbers as keys to a hash, Perl turns them into strings, which you'll probably never notice (except if you then use them as numbers and discover minute rounding errors -- see tom phoenix's i in tpj#8). However, when you try to use an object value as a key in a hash (such as a hash mapping Net::FTP sessions to hostnames), Perl will turn it into a string, making it useless. Three solutions to this problem are: 1) Reconsider whether you can actually have your hash be the other way around. Since the I can be of any type, you might be able to just map hostnames (strings) to connection object-values, for example. Of course, this works only if you're sure that what you currently have as hash values (here, hostnames) are unique. 2) Keep the objects in a second hash, called maybe %really, and whenever you set a value in your main hash, also set C<$really{$object} = $object>. Later, when you want to do something with the object values, instead of using whatever the key in the main hash is, use $really{$that_key}. 3) If you're familiar with references, then you can have the hash-values each be a reference to a hash or list that contains the object value. For example, instead of trying this: $main{$session} = $hostname; have %main be a hash of array-references: $main{$session} = [$session, $hostname]; Later, when you're dealing with the hash, you'll find the real (still good, not stringified) object value in C<$main{I}[0]>, and the hostname in C<$main{I}[1]>. Occasionally I hear of suggestions for future versions of Perl to be changed to allow using real object values as keys in a hash (instead of taking their string representation, and using that). If this happens, the problem I've described will disappear. But in the meantime, it's important to understand the current problem, and the ways around it. =head2 So Why Do Some Modules Use Objects? 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? A somewhat esoteric answer is that a module has an object-oriented interface because the module's whole insides are written in an object-oriented style. This article is about the basics of object-oriented I, and it'd be going far afield to explain what object-oriented 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. 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 one at a time, with code like: open("foo.txt") || die "Can't open foo: $!"; while(readline) { print $_ if /bar/; } close; and that hypothetical kind of Perl would be simpler, by doing without filehandles, is simpler. However, 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. In the same way, a functional FTP 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 sense only in terms of I simultaneous sessions 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"). Some kinds of problems that modules solve just loan 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. __END__ Sean M. Burke has contributed several modules to CPAN, about half of them object-oriented. [The next section should be in a greybox, I think:] =head2 The Gory Details For sake of clarity of explanation, I had to oversimplify some of the facts about objects. Here's a few of the gorier details: * 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: $new = $old->copy, $node_y = $node_x->new_subnode, or the like. * 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. * I said that C was for testing whether something was an object -- it's really for testing whether something is a reference (and reporting its type/class if it is). Objects are just one kind of reference. * 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. * I mentioned creating objects with Istructors, but I didn't mention destroying them with Istructor -- 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. * I said that class method syntax has to have the class name, as in $session = B->new($host). Actually, you can instead use any expression that returns a class name: $ftp_class = 'Net::FTP'; $session = B<$ftp_class>->new($host). Moreover, instead of the method name for object- or class-method calls, you can use a scalar holding the method name: $foo->B<$method>($host). But, in practice, these syntaxes are rarely useful. * CGI.pm's interface is very strange because it provides both a functional and object-oriented interface. It's only in rare cases that you'd I to use its object-oriented interface, but many people seem to consider that the normal way to do it. And finally, to learn about objects from the perspective of writing your own classes, see the C documentation, or Damian Conway's exhaustive and clear book I (Manning Publications 1999, ISBN 1-884777-79-1).