in reply to Re: A class that cannot be subclassed.
in thread A class that cannot be subclassed.

Well, that *almost* completely works. Where it can fail is if the parent is in a class hierarchy itself, and that framework uses methods from the entire hierarchy. You can't override those. For example:

package GP; sub foo { my $self = shift; # ... $self->bar(); # ... } sub bar { my $self = shift # but I can be overridden } package P; sub bar { my $self = shift; # stuff. }
Assuming P could prevent subclassing (I'm not sure how, and I still fail to see why, but that's not relevant here), any attempt for your Decorator to override bar when calling $obj->foo() is doomed to failure.

Problem #2 (though this isn't quite as problematic in Perl as it is in other languages - I only bring it up because you say your decorator works "in every single language"): checking the type of the object. If I were to pass around an object of type Decorator, perl allows this to work as long as no one checks what Decorator *is*. e.g., code that checks $obj->isa("P") will fail. Now, granted, you can override isa. Of course, then there are people who advocate reversing this, and calling UNIVERSAL::isa($obj, "P") (does that count as a way to test for it?), and you can't stop that as far as I know. Update: of course you can, this IS perl, after all... so I have to assume there's a way to get ref $decorator_object to return "P", too...

Even perl6 introduces some problems here - if I already have a function somewhere that takes a parameter of type "P", an object of type "Decorator" won't suffice. Other languages, such as C++ or Java, already have this: if you create a decorator generic, say Decorator<T>, and try to pass that around as if it were of type T, it won't really work. Now, in all these languages, you probably can override an implicit conversion of Decorator to the parent type (where you return $self->parent()), but you'll again lose all over your method overrides.

Replies are listed 'Best First'.
Re^3: A class that cannot be subclassed.
by chromatic (Archbishop) on Feb 29, 2008 at 00:18 UTC
    Of course, then there are people who advocate reversing this, and calling UNIVERSAL::isa($obj, "P") (does that count as a way to test for it?), and you can't stop that as far as I know.

    Sure you can. UNIVERSAL::isa does just that to prevent people from breaking things like Test::MockObject.