This file is automatically generated. If you wish to submit a PR, do not
edit this file directly. Please edit
templates/rfc/faq.md instead. Use bin/generate_rfc.pl
to regenerate the RFCs.
You have questions? We have answers. Note that this is a work-in-progress. More may be added later.
Post-MVP this decision might be revisited, but for the MVP, we needed to constrain the problem space. Just some of the issues being faced:
class
will understand the difference between methods and subroutines and when the MVP is more fleshed out, will not allow you to call subroutines as methods. What do you do when the parent class isblessed
ed and all you have are subs?class
is single-inheritance andbless
is multiple inheritance. Having to switch the MRO back and forth as you walk the inheritance hierarchy is begging for bugs.- Ultimately,
class
might need a different base class, such asUNIVERSAL::Class
. If we inherit from abless
ed object, which base class wins? - Many awesome tools have been written for Moose and they assume Class::MOP works. We cannot make that assumption, so we don't.
Post-MVP, we might revision this decision, but for the MVP, there's a huge
amount of work to do and trying to make sure we didn't screw up anywhere is
much harder if we try to slurp in the entire bless
ed ecosystem. Bear with
us.
Otherwise, you can try the Object::Pad module. That's been the test bed for Corinna and it does allow inheriting from legacy objects. Caveat Emptor.
No, you can't. Sorry. You can try Object::Pad
, not use class
, or
investigate composition over inheritance:
class My::Class {
use Some::Bless::Class;
field $arg_for_blessed :param(arg);
field $delegate = Some::Bless::Class->new($arg_for_blessed);
method to_delegate (@args) {
return $delegate->some_method(@args);
}
}
None of those answers are satisfactory, but this is an MVP.
If you write this:
class My::Class {
field $name;
sub get_name ($self) { $name }
}
That's a syntax error because we can't access the instance variable $name
from a subroutine. They don't know what instance variables are. Or consider
these;
class Example1 {
sub sum ($self) { ... }
}
class Example2 {
use List::Util 'sum';
}
In both cases, we have a sum
subroutine, but for the first, it's clearly
intended to be a method and not a helper function. From the outside, we have
no way of knowing that. class
makes a clear distinction between methods and
subroutines and when the MVP is complete, $class->can('sum')
should return
false if sum
is a subroutine and not a method.
No. Well, if you tried to slap it into an existing procedural code and you had subroutines with conflicting names to the keywords, maybe. Or you could use a lexical block and it should be perfectly safe:
# lots of code here
{
use feature 'class';
class Foo ...
}
# more code here, but it doesn't see `class` behavior
Otherwise, class
objects can call methods on bless
objects and vice-versa
without problem.
Er, you probably shouldn't. Rewriting is okay, but refactoring is a different story.
If you wanted to experiment, keep this in mind: a class
cannot inherit from
bless
ed objects, but as of this writing, a bless
ed object can inherit
from a class
object. So go to the root of your object hierarchy and look at
converting that to a class
and see what happens.
For any decent-sized system, you're going to have too many edge cases for this
to be easy (or sane). For example, class
constructors require an even-sized
list of key/value pairs. Many other constructors don't. You may need to
rethink your constructor strategy.
At the end of the day, trying to gradually mix-and-match an OOP hierarchy from
bless
to class
is like trying to use motorcycle parts to fix a car. Maybe
you'll get lucky and it works, but probably not for larger codebases (at least,
not without a lot of heavy lifting).
The above is for refactoring. However, you could rewrite existing objects via
the new class
syntax. If your tests are sane, that may not be too hard.
However, if people are using your code, they may not be in a position to
upgrade to v5.38.0. You could investigate
Feature::Compat::Class, but
read the docs carefully. There are potential compatibility issues.
Yes! Check out Chris "peregrin" Prather's Roguelike
tutorial. It's pretty amazing and
shows that class
is more powerful than your author suspected (I thought we'd
need more features to get this far. I was wrong).
Stevan "Damn it" Little is writing Stella,
an actor model written with class
. So far, he's been very pleased with how
easy class
is to work with.
Not quite. A class
keyword declares a class and a namespace. A package
keyword just declares the namespace. They both have the same scoping rules.
What this means, however, is that you can use class
similarly to how you
would use a package
.
For example, if you have a file named lib/My/Awesome/Class.pm
, you won't need
a package
statement inside if you use class
instead:
use experimental 'class';
class My::Awesome::Class;
# more code here ...
No, it's not. Like the package
keyword, the postfix block is optional. I
prefer it for the extremely clear scoping. You don't need to use it if you
don't want to.
There's a tutorial at perlclasstut.pod.
Note that this tutorial is for the full MVP. If you're reading this before the full MVP is released, some of the features in that tutorial won't yet be working. I don't know what version of Perl you have installed, so you'll need to consult your documentation.
If you prefer, here's a gist of the tutorial, formatted via markdown. It's not guaranteed to be kept up-to-date.
The experimental class
feature was first added in Perl v5.38.0. You'll want
to check perldoc perlclass
for your version of Perl. You can also read it
online, but be sure to select the correct
version of Perl from the menu at the top.