Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re^3: Thoughts on new 'class' OO in upcoming perl

by cavac (Prior)
on Mar 06, 2023 at 14:56 UTC ( [id://11150788]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Thoughts on new 'class' OO in upcoming perl
in thread Thoughts on new 'class' OO in upcoming perl

How would you prevent someone from calling new() directly, in this case skipping your argument checks?

PerlMonks XP is useless? Not anymore: XPD - Do more with your PerlMonks XP
  • Comment on Re^3: Thoughts on new 'class' OO in upcoming perl

Replies are listed 'Best First'.
Re^4: Thoughts on new 'class' OO in upcoming perl
by tobyink (Canon) on Mar 06, 2023 at 15:11 UTC
      Technically correct, but it ignores one little detail: Calling ->new is the normal, default way to create an object. Calling bless directly is not.

      There's quite a difference between expecting people to not instantiate an object in a way which 99% of classes consider to be an unsupported backdoor "here be dragons" approach (bless) and expecting them to not instantiate it in a way which 99% of classes consider to be the standard way to do it (calling the ->new method).

Re^4: Thoughts on new 'class' OO in upcoming perl
by haj (Vicar) on Mar 06, 2023 at 20:07 UTC
    How would you prevent someone from calling new() directly, in this case skipping your argument checks?

    Actually, this is possible. Your valid constructor methods just create a sufficiently secure random token and pass this to new. Here's a simple example where you can create objects with calls to the valid_constructor function, but not by directly calling new:

    use 5.37.9; use feature 'class'; no warnings 'experimental'; class No::New { use Carp; field $token :param; my %valid_tokens; ADJUST { delete $valid_tokens{$token} or croak "Directly calling ", __PACKAGE__, "->new is forbidden"; } sub valid_constructor { my $token = rand; $valid_tokens{$token} = 1; __PACKAGE__->new(token => $token); } method text { "Congratulations!"; } } say No::New->valid_constructor->text;

    Such a technique, as already mentioned by tobyink, is entirely impossible for bless. Since all "traditional" Perl OO frameworks including Object::Pad are based on blessed references, only core OO can prevent objects like bless \q"Arbitrary junk", Your::Class from happening!

      A slightly neater way:

      use 5.37.9; no warnings qw( experimental ); use feature qw( class defer ); use builtins qw( true false ); class No::New { use Carp; my $allow_construction = false; ADJUST { croak "Directly calling @{[ __PACKAGE__ ]}->new is forbidden" unless $allow_construction; } sub create { my $class = shift; $allow_construction = true; defer { $allow_construction = false }; return $class->new; } method text { "Congratulations!"; } } say No::New->create->text;

      (Note: I haven't actually tried this as the most recent Perl I have installed is 5.37.2.)

        A nice demonstration of the new defer feature!

        My less neat way is required only if you want to prohibit another call to No::New->new that happens somewhere in the innards of an ADJUST block.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11150788]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (4)
As of 2025-06-13 20:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.