Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Possibly Stupid OOP question

by talwyn (Monk)
on Feb 27, 2008 at 00:25 UTC ( #670444=perlquestion: print w/replies, xml ) Need Help??
talwyn has asked for the wisdom of the Perl Monks concerning the following question:

The following code tells me that no new sub can be found in package STRTicket. While true technically... the @ISA is supposed to enable inheritance... I thought. In this case the empty sub class fails.

All classes are in the same monolithic source file. USE doesn't appear to like that and searches for actual .pm files... so I used import which seems to give me the symboltables (Ticket->new works for instance... but inheritance appears to fail ( Empty sub-class test fails). So What... if anything else am I supposed to do when everything is in a single file to use an object and its subclasses?

my $t = new STRTicket(); package Ticket; sub new { my $class = shift; my $ticketid = shift; my $self= { 'TICKETID' => undef, 'SOURCE' => undef, 'CREATEDBY' => undef, 'OWNER' => undef, 'MODIFIEDBY'=> undef, 'CREATEDON' => undef, 'MODIFIEDON'=> undef, 'COMPANYNAME'=> undef, 'STATE' => undef, 'STATUS' => undef, 'BZTICKETS' => (), 'AGE' => undef, 'TITLE' => undef, }; bless $self, $class; if ( defined $ticket) { $self->{'TICKETID'} = $ticket; } else { die "Ticket object instantiated without a ticket id! This shou +ld never happen.\n"; } return $self; } sub load_bztickets($){ my $self= shift; my $dbh = shift; # pass in the database reference for Bugzilla } 1; package BZTicket; import Ticket; # use Ticket; @ISA = ('Ticket'); 1; package CRMTicket; import Ticket; #use Ticket; @ISA = ('Ticket'); 1; package STRTicket; import Ticket; # use Ticket; @ISA = ('Ticket'); 1;

Replies are listed 'Best First'.
Re: Possibly Stupid OOP question
by ysth (Canon) on Feb 27, 2008 at 02:13 UTC
    If you have classes in the same source in which they are used, you need to make sure the inheritance tree is set up before it is used. Often, this means putting the @ISA = into a BEGIN block.

    Your imports appear to me to be useless. re your new and import calls, please try to avoid indirect object syntax ("method $object args", or "method Class args"). Use $object->method(args) or Class->method(args) instead. Indirect object syntax has some gotchas.

      It also helps to put the classes higher in the source file than the uses of them (which matches how classes get used when in separate files). The good practices that you described are also ways to overcome not using this "natural order" but it can still be a good idea to stick to the usual order.

      I'll also note that the original code smells like a typical design made after reading a typical introduction to OO programming. Jumping to using inheritance is probably the most common mistake made by OO programmers who haven't yet become old and tired. Old, tired OO programmers have learned that an "is a" relationship is very tight and quite inflexible and so should be reserved for rather rare cases and only used for a very fundamental connection (and that fundamental connections can still usually be better implemented without inheritance).

      - tye        

        It is funny that most OO books bang on about inheritance so much when the guy who invented the term OO thinks that OO is:

        "OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things." -- Alan Kay

        Bots of the disorder.

Re: Possibly Stupid OOP question
by NetWallah (Abbot) on Feb 27, 2008 at 01:42 UTC
    use base qw{ Ticket }; fixes all the evil things you attempt via "import" and "@ISA".

    I also fixed other minor things to make this work:

         "As you get older three things happen. The first is your memory goes, and I can't remember the other two... " - Sir Norman Wisdom

Re: Possibly Stupid OOP question
by runrig (Abbot) on Feb 27, 2008 at 00:32 UTC
    If it's all in the same source file, the STRTicket->new() should come last (preferably after a package main;).
      ok ... if the package isn't declared ( top part of the code ) then its automagically in Main:: isn't it?

      If so, package ticket and STRTicket both follow package main. I generally like the core of my program at the top of the source file and refer to sub below. Until now it has always worked. Am I missing your point?

        @ISA = ... is just an assignment. It's not happening until AFTER your call to new(). So there is no inheritance until AFTER all of your packages. Perhaps putting each of the @ISA=...'s in BEGIN{...} blocks will work. (Maybe putting all of the packages in one big BEGIN {...} block will work? Update: Yes, it does seem to work).
Re: Possibly Stupid OOP question
by runrig (Abbot) on Feb 27, 2008 at 00:52 UTC
      The compiler complained unless import was used. I assumed it wasn't aware of the other package.

      Thanks for the BEGIN{} hint, that seemed to do the trick.

      As far as strict and warnings, this is a code snippet, the larger app does indeed use strict

      Again Thanks !

Re: Possibly Stupid OOP question
by dsheroh (Prior) on Feb 27, 2008 at 04:06 UTC
    All classes are in the same monolithic source file. USE doesn't appear to like that and searches for actual .pm files...

    That is correct. Since packages almost always have a one-to-one relationship with .pm files which share the same name, it's easy to start thinking of them as interchangable, but they're not.

    use specifies a file to read, no more and no less. The package(s) contained within that file are defined solely by the package statement(s) it contains.

    For example, if you have a file named containing

    package Bar; use strict; use warnings; sub hi { print "Hello, world!\n"; } 1;
    then you would load its contents with use Foo, but execute them with Bar::hi. This is, obviously, a little confusing in most cases, which is why the convention of using the same name for the file and the package exists. But it's just a convention, not something enforced (or even recognized) by the language.
Re: Possibly Stupid OOP question
by ikegami (Pope) on Feb 27, 2008 at 06:48 UTC

    Why import from a package that doesn't export anything?

    Only when the package starts exporting something *and* the would-be importer uses some of those exported functions does your issue surface, and that's not likely to happen with packages that are classes.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://670444]
Approved by John M. Dlugosz
and a soft breeze sighs...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (2)
As of 2017-04-28 23:45 GMT
Find Nodes?
    Voting Booth?
    I'm a fool:

    Results (531 votes). Check out past polls.