File Coverage

blib/lib/Feature/Compat/Class.pm
Criterion Covered Total %
statement 15 15 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 20 20 100.0


line stmt bran cond sub pod time code
1             # You may distribute under the terms of either the GNU General Public License
2             # or the Artistic License (the same terms as Perl itself)
3             #
4             # (C) Paul Evans, 2022-2025 -- leonerd@leonerd.org.uk
5              
6             package Feature::Compat::Class 0.08;
7              
8 13     13   3044826 use v5.14;
  13         77  
9 13     13   82 use warnings;
  13         29  
  13         735  
10 13     13   76 use feature ();
  13         26  
  13         383  
11              
12 13     13   80 use constant HAVE_FEATURE_CLASS => $^V ge v5.42;
  13         52  
  13         3723  
13              
14             =head1 NAME
15              
16             C - make C syntax available
17              
18             =head1 SYNOPSIS
19              
20             use Feature::Compat::Class;
21              
22             class Point {
23             field $x :param :reader :writer = 0;
24             field $y :param :reader :writer = 0;
25              
26             method move_to ($new_x, $new_y) {
27             $x = $new_x;
28             $y = $new_y;
29             }
30              
31             method describe {
32             say "A point at ($x, $y)";
33             }
34             }
35              
36             Point->new(x => 5, y => 10)->describe;
37              
38             =head1 DESCRIPTION
39              
40             This module provides the new C keyword and related others (C,
41             C and C) in a forward-compatible way.
42              
43             Perl added such syntax at version 5.38.0, which is enabled by
44              
45             use feature 'class';
46              
47             This syntax was further expanded in 5.40, adding the C<__CLASS__> keyword and
48             C<:reader> attribute on fields, and again in 5.42 to add the C<:writer>
49             attribute.
50              
51             On that version of perl or later, this module simply enables the core feature
52             equivalent of using it directly. On such perls, this module will install with
53             no non-core dependencies, and requires no C compiler.
54              
55             On older versions of perl before such syntax is availble in core, it is
56             currently provided instead using the L module, imported with a
57             special set of options to configure it to only recognise the same syntax as
58             the core perl feature, thus ensuring any code using it will still continue to
59             function on that newer perl.
60              
61             This module is a work-in-progress, because the underlying C
62             is too. Many of the limitations and inabilities listed below are a result of
63             the early-access nature of this branch, and are expected to be lifted as work
64             progresses towards a more featureful and complete implementation.
65              
66             =cut
67              
68             sub import
69             {
70 12     12   85 if( HAVE_FEATURE_CLASS ) {
71 12         1568 feature->import(qw( class ));
72 12         73 require warnings;
73 12         22906 warnings->unimport(qw( experimental::class ));
74             }
75             else {
76             require Object::Pad;
77             Object::Pad->VERSION( '0.823' ); # :config(writer_only_scalar)
78             Object::Pad->import(qw( class method field ADJUST ),
79             ':experimental(init_expr)',
80             ':config(' .
81             'always_strict only_class_attrs=isa only_field_attrs=param,reader,writer ' .
82             'no_field_block no_adjust_attrs no_implicit_pragmata writer_only_scalar' .
83             ')',
84             );
85             }
86             }
87              
88             =head1 KEYWORDS
89              
90             The keywords provided by this module offer a subset of the abilities of those
91             provided by C, restricted to specifically only what is commonly
92             supported by the core syntax as well. In general, the reader should first
93             consult the documentation for the corresponding C keyword, but
94             the following notes may be of interest:
95              
96             =head2 class
97              
98             class NAME { ... }
99             class NAME VERSION { ... }
100              
101             class NAME; ...
102             class NAME VERSION; ...
103              
104             See also L.
105              
106             There is no ability to declare any roles with C<:does>. The legacy subkeywords
107             for these are equally not supported.
108              
109             The C<:repr> attribute is also not supported; the default representation type
110             will always be selected.
111              
112             The C<:strict(params)> attribute is not available, but all constructed classes
113             will behave as if the attribute had been declared. Every generated constructor
114             will check its parameters for key names left unhandled by C blocks,
115             and throw an exception if any remain.
116              
117             The following class attributes are supported:
118              
119             =head3 :isa
120              
121             :isa(CLASS)
122              
123             :isa(CLASS CLASSVER)
124              
125             I
126              
127             Declares a superclass that this class extends. At most one superclass is
128             supported.
129              
130             If the package providing the superclass does not exist, an attempt is made to
131             load it by code equivalent to
132              
133             require CLASS ();
134              
135             and thus it must either already exist, or be locatable via the usual C<@INC>
136             mechanisms.
137              
138             An optional version check can also be supplied; it performs the equivalent of
139              
140             BaseClass->VERSION( $ver )
141              
142             Note that C blocks B implicitly enable the C and
143             C pragmata; either when using the core feature or C.
144             This is to avoid surprises when eventually switching to purely using the core
145             perl feature, which will not do that. Remember however that a C
146             of a version C or above will enable both these pragmata anyway, so that
147             will be sufficient.
148              
149             =head2 method
150              
151             method NAME { ... }
152             method NAME;
153              
154             See also L.
155              
156             Attributes are not supported, other than the usual ones provided by perl
157             itself. Of these, only C<:lvalue> is particularly useful.
158              
159             Lexical methods are not supported.
160              
161             =head2 field
162              
163             field $NAME;
164             field @NAME;
165             field %NAME;
166              
167             field $NAME = EXPR;
168              
169             field $NAME :ATTRS... = EXPR;
170              
171             See also L.
172              
173             Most field attributes are not supported. In particular, rather than using the
174             accessor-generator attributes you will have to create accessor methods
175             yourself; such as
176              
177             field $var;
178             method var { return $var; }
179             method set_var ($new_var) { $var = $new_var; }
180              
181             I fields of any type may take initialising expressions.
182             Initialiser blocks are not supported.
183              
184             field $five = 5;
185              
186             I field initialiser expressions can see earlier fields
187             that have already been declared, and use their values:
188              
189             field $fullname :param;
190             field $shortname :param = ( split m/ +/, $fullname )[0];
191              
192             The following field attributes are supported:
193              
194             =head3 :param
195              
196             field $var :param;
197              
198             field $var :param(name)
199              
200             I
201              
202             Declares that the constructor will take a named parameter to set the value for
203             this field in a new instance.
204              
205             field $var :param = EXPR;
206              
207             Without a defaulting expression, the parameter is mandatory. When combined
208             with a defaulting expression, the parameter is optional and the default will
209             only apply if the named parameter was not passed to the constructor.
210              
211             field $var :param //= EXPR;
212             field $var :param ||= EXPR;
213              
214             With both the C<:param> attribute and a defaulting expression, the operator
215             can also be written as C or C<||=>. In this case, the defaulting
216             expression will be used even if the caller passed an undefined value (for
217             C) or a false value (for C<||=>). This simplifies many situations where
218             C would not be a valid value for a field parameter.
219              
220             class C {
221             field $timeout :param //= 20;
222             }
223              
224             C->new( timeout => $args{timeout} );
225             # default applies if %args has no 'timeout' key, or if its value is undef
226              
227             =head3 :reader, :reader(NAME)
228              
229             I
230              
231             Generates a reader method to return the current value of the field. If no name
232             is given, the name of the field is used. A single prefix character C<_> will
233             be removed if present.
234              
235             field $x :reader;
236              
237             # equivalent to
238             field $x; method x () { return $x }
239              
240             These are permitted on an field type, not just scalars. The reader method
241             behaves identically to how a lexical variable would behave in the same
242             context; namely returning a list of values from an array or key/value pairs
243             from a hash when in list context, or the number of items or keys when in
244             scalar context.
245              
246             field @items :reader;
247              
248             foreach my $item ( $obj->items ) { ... } # iterates the list of items
249              
250             my $count = $obj->items; # yields count of items
251              
252             =head3 :writer, :writer(NAME)
253              
254             I
255              
256             Generates a writer method to set a new value for the field. If no name is
257             given, the name of the field is used with a C prefix. If a name is
258             provided that will be used - you should remember to add a distinguishing
259             prefix if required to keep it distinct from the reader method. A single
260             prefix character C<_> will be removed if present.
261              
262             field $x :writer;
263              
264             # equivalent to
265             field $x; method set_x ($new_x) { $x = $new_x; return $self; }
266              
267             When invoked, a C<:writer> method will return the invocant object itself.
268             This is so that multiple fields can be modified in a convenient chaining
269             syntax; for example:
270              
271             $obj->set_x( 10 )
272             ->set_y( 20 )
273             ->set_z( 30 );
274              
275             =head2 ADJUST
276              
277             ADJUST { ... }
278              
279             See also L.
280              
281             Attributes are not supported; in particular the C<:params> attribute of
282             C v0.70.
283              
284             =head2 __CLASS__
285              
286             my $classname = __CLASS__;
287              
288             I
289              
290             Only valid within the body (or signature) of a C, an C block,
291             or the initialising expression of a C. Yields the class name of the
292             instance that the method, block or expression is invoked on.
293              
294             This is similar to the core perl C<__PACKAGE__> constant, except that it cares
295             about the dynamic class of the actual instance, not the static class the code
296             belongs to. When invoked by a subclass instance that inherited code from its
297             superclass it yields the name of the class of the instance regardless of which
298             class defined the code.
299              
300             For example,
301              
302             class BaseClass {
303             ADJUST { say "Constructing an instance of " . __CLASS__; }
304             }
305              
306             class DerivedClass :isa(BaseClass) { }
307              
308             my $obj = DerivedClass->new;
309              
310             Will produce the following output
311              
312             Constructing an instance of DerivedClass
313              
314             This is particularly useful in field initialisers for invoking (constant)
315             methods on the invoking class to provide default values for fields. This way a
316             subclass could provide a different value.
317              
318             class Timer {
319             use constant DEFAULT_DURATION => 60;
320             field $duration = __CLASS__->DEFAULT_DURATION;
321             }
322              
323             class ThreeMinuteTimer :isa(Timer) {
324             use constant DEFAULT_DURATION => 3 * 60;
325             }
326              
327             =head2 Other Keywords
328              
329             The following other keywords provided by C are not supported here
330             at all:
331              
332             role
333              
334             BUILD, ADJUSTPARAMS
335              
336             has
337              
338             requires
339              
340             =cut
341              
342             =head1 COMPATIBILITY NOTES
343              
344             This module may use either L or the perl core C feature to
345             implement its syntax. While the two behave very similarly and both conform to
346             the description given above, the following differences should be noted.
347              
348             =over 4
349              
350             =item I
351              
352             =back
353              
354             =cut
355              
356             =head1 AUTHOR
357              
358             Paul Evans
359              
360             =cut
361              
362             0x55AA;