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


in reply to Re^2: A Growing Dislike for SQL-OOP Mappers
in thread A Growing Dislike for SQL-OOP Mappers

The problem has nothing to do with SQL-OOP mapping; it's just general OOP. In the end, if you override create and another Class::DBI method (such as find_or_create) calls $self->create, it is perfectly natural that it will call your overriden method. That's what polymorphism is all about.

Think about it the other way: if it worked the way you want, someone would soon complain that they overrode create and called find_or_create expecting it to call their overriden create, but it didn't.

If you create an infinite loop or somesuch thing by overriding create, you should reconsider your strategy. You can either override find_or_create as well, or hack your method to keep state so that it breaks out of the loop.

Replies are listed 'Best First'.
Re^4: A Growing Dislike for SQL-OOP Mappers
by jk2addict (Chaplain) on Aug 22, 2005 at 21:33 UTC
    If you create an infinite loop or somesuch thing by overriding create, you should reconsider your strategy

    I agree. So, who needs create. It's a silly name. The same could be said about new....so in the same type of situation, I can't override new in the subclass? That's wrong IMHO. There should never be a situation where I can't provide my own new(). And I don't really think and SUPER class methods calling new on itself or it's subclass is quite kosher either; but it happens.

      There's nothing special about new() in Perl -- it's the same as any other method. You can override it, and you will have the same trials and tribulations with overriding it that you would have with any other inheritance scenario. It still sounds like you're complaining that you don't like OOP to me.
        Well, I think it's a real problem for the dispatcher not to know the difference between abstract interface methods and infrastructural methods, which is why Perl 6 introduces the concept of "submethods" that are callable from outside the class, but only if there's an exact type match on the invocant. Otherwise the dispatcher keeps looking for a more appropriate method or submethod to dispatch to.

        (There's also the concept of completely private methods that aren't visible from outside the class at all, but that's really a different beastie altogether.) Anyway, I think use of submethods would probably solve the first problem of the OP.

      I never said "don't override it", I even proposed two ways you could do it! This is a general situation: if you want to override method A so that it calls method B, and you know that method B will call method A, you can fix the loop by overriding method B. For example,
      package MyApp::DBI; use base 'Class::DBI'; __PACKAGE__->connection(...); 1; package MyApp::Gallery; use base 'MyApp::DBI'; __PACKAGE__->table('galleries'); __PACKAGE__->columns(...); sub create { my ($self, $ops) = @_; my $dir = $ops->{'directory'}; if (-e $dir) { die 'directory exists'; else { mkdir $directory; $self->find_or_create($data); }; return; }; sub find_or_create { my $class = shift; my $hash = ref $_[0] eq "HASH" ? shift: {@_}; my ($exists) = $class->search($hash); return defined($exists) ? $exists $class->SUPER::create($hash) +; } 1;