http://qs321.pair.com?node_id=1194238


in reply to Perl OOP

The other monks have already provided some good answers, I just wanted to add a few more thoughts:

  1. Quoting the Camel (the Perl book, which I can highly recommend especially since you already have a coding background), Chapter 11:

    Perl does not automatically patrol private/public borders within its modules - unlike languages such as C++, Java, and Ada, Perl isn't obsessed with enforced privacy. A Perl module would prefer that you stay out of its living room because you weren't invited, not because it has a shotgun.

    I know this isn't exactly the topic you're asking about, but I think it expresses this part of the Perl philosophy quite well. In Perl, you can generally reach into any classes' internals if you wanted to, extend them with monkey patching, etc., and class authors usually won't try to stop you. But if you break something by doing something you shouldn't have, it's your fault :-) (Update: I should make it more clear that although you could do the aforementioned things, they are certainly not recommended for readable/maintainable code!)

    This idea extends into other areas as well: sure, you could make all your constants Readonly, but OTOH, you could trust that others will see variable names in all caps and know that they shouldn't be modified; if they do then anything that breaks is their fault. Because I myself tend to code defensively, I can tell you that this idea can take some getting used to. (As an aside, it should be noted that even in Java, sometimes it's necessary to look into an Object's private variables, and that is indeed possible with its Reflection API.)

  2. AFAIK, the primary purpose of Java's hashCode is to assist with storing objects in Java's hash tables. In Perl, hashes are indexed by strings, and any variable you try to use as a hash key will be forced into a string form. You also normally wouldn't use an object as a key for a hash - plain objects will stringify to something like "Object=HASH(0xa81262)" - although theoretically unique because it's based on the memory address, it's not really useful for lookups etc. Normally one would choose a useful string as the hash key. (There are of course some objects that stringify to useful values and that can be then turned back into those objects from strings, for example Math::BigInt, or DateTime via e.g. DateTime::Format::Strptime.)

    As for equals, note that even in Java there is often a problem with defining this method properly - e.g., are two ORM objects equal when they have the same primary key, or when all of their other fields match, or some combination of both? And then there are lots of cases where it doesn't even make sense to compare objects for "equality" other than comparing their memory addresses. So it has to be defined on a case-by-case basis, and if you want to compare Perl objects, it's the same, each class will have to define its own method to answer the question "am I equal to some other object?" - Perl does not place any requirement on this. (There is also the possibility to overload objects so that they can be compared with operators like eq, but this is an advanced topic, and many Perl classes don't use it.)

  3. No, as others have said, this isn't usually necessary in Perl. Let's say you have an object that stores other objects, you can just say: $collection->get($index)->some_method(), and the ->some_method() call will be looked up dynamically on the object that ->get() returns, regardless of what it is. (You can even do slightly wacky things like store the method name in a variable and say $collection->get($index)->$some_method_name. Update 2: Again, not recommended for normal practice, I'm just using this as an example as to just how dynamic method lookups are.)

    If you wanted to make sure that your "collection" only contains objects of one class, then you'd have to add code to enforce this yourself (lots of different ways to do that, also depending on whether an OO framework is being used, so I won't get into that here). Perl's native types like @arrays and %hashes don't have any mechanism like generics, although if you wanted to get into advanced topics, then it's possible to use tied variables that could enforce this - but I haven't yet seen that level of defensive coding.

In general, for getting into Perl OO programming, I think Modern Perl is a good choice. When you read it, you might notice that Perl's objects can actually be very simple: they start out as references to anonymous hashes (usually), that are then "blessed" into their class. There aren't many other requirements for objects, you can even freely choose the name of their constructor, it doesn't have to be new. And you'll probably notice that unlike languages like Java, not every script/program needs to be OO, so my suggestion would be to first work on some Perl scripts without OO, then learn about blessed references (e.g. from the chapter "Blessed References" in Modern Perl), and then look at full-featured OO frameworks like Moose or Moo.