File Coverage

blib/lib/PDLx/DetachedObject.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 5 5 100.0
pod 2 2 100.0
total 19 19 100.0


line stmt bran cond sub pod time code
1             # ABSTRACT: parent class for subclassing PDL 2.X from class frameworks
2             package PDLx::DetachedObject;
3              
4 2     2   224376 use strict;
  2         5  
  2         49  
5 2     2   9 use warnings;
  2         4  
  2         110  
6              
7             our $VERSION = '0.02';
8              
9             our @ISA = qw( PDL );
10 2     2   356 use PDL::Lite;
  2         135715  
  2         14  
11              
12             #pod =begin pod_coverage
13             #pod
14             #pod =head3 initialize
15             #pod
16             #pod =head3 new
17             #pod
18             #pod =end pod_coverage
19             #pod
20             #pod =cut
21              
22 10     10 1 83094 sub initialize { return PDL->null }
23              
24             sub new {
25 1     1 1 4642 my $class = shift;
26 1         5 bless { PDL => PDL->null }, $class;
27             }
28              
29             1;
30              
31             #
32             # This file is part of PDLx-DetachedObject
33             #
34             # This software is Copyright (c) 2016 by Smithsonian Astrophysical Observatory.
35             #
36             # This is free software, licensed under:
37             #
38             # The GNU General Public License, Version 3, June 2007
39             #
40              
41             =pod
42              
43             =encoding UTF-8
44              
45             =head1 NAME
46              
47             PDLx::DetachedObject - parent class for subclassing PDL 2.X from class frameworks
48              
49             =head1 VERSION
50              
51             version 0.02
52              
53             =head1 SYNOPSIS
54              
55             =head3 Moo
56              
57             # DEPRECATED; use MooX::PDL2 instead
58             package MyPDL;
59              
60             use Moo;
61             use PDL::Lite;
62              
63             extends 'PDLx::DetachedObject';
64              
65             has PDL => ( is => 'rw' );
66              
67             =head3 Class::Tiny
68              
69             package MyPDL;
70              
71             use Class::Tiny qw[ PDL ];
72              
73             use parent 'PDLx::DetachedObject';
74              
75             =head3 Object::Tiny
76              
77             package MyPDL;
78              
79             use Object::Tiny qw[ PDL ];
80              
81             use parent 'PDLx::DetachedObject';
82              
83             =head3 Class::Accessor
84              
85             package MyPDL;
86              
87             use parent 'Class::Accessor', 'PDLx::DetachedObject';
88             __PACKAGE__->follow_best_practice;
89             __PACKAGE__->mk_accessors( 'PDL' );
90              
91             or with Antlers:
92              
93             package MyPDL;
94             use Class::Accessor "antlers";
95             use parent 'PDLx::DetachedObject';
96              
97             has PDL => ( is => 'ro' );
98              
99             =head1 DESCRIPTION
100              
101             B provides a minimal shim between L and
102             object-orientation frameworks. Directly subclassing B is tricky,
103             as a B object (a piddle) is a blessed scalar, not a blessed hash.
104             B provides an L means of subclassing; this
105             class encapsulates that prescription.
106              
107             For L based classes, see L, which provides a more
108             integrated approach.
109              
110             =head2 Background
111              
112             Because a B object is a blessed scalar, outside of using
113             inside-out classes as the subclass, there is no easy means of adding
114             extra attributes to the object.
115              
116             To work around this, B will treat any hash blessed into a
117             subclass of PDL which has an entry with key C whose value is a
118             real B object as a B object.
119              
120             So far, here's a L<< B >> version of the class
121              
122             package MyPDL;
123              
124             use Moo;
125              
126             extends 'PDL';
127              
128             # don't pass any constructor arguments to PDL->new; it confuses it
129             sub FOREIGNBUILDARGS {}
130              
131             has PDL => ( is => 'rw' );
132             has required_attr => ( is => 'ro', required =>1 );
133              
134             When B needs to instantiate an object from the subclass,
135             it doesn't call the subclass's constructor, rather it calls the
136             B class method, which is expected to return a hash,
137             blessed into the subclass, containing the C key as well as any
138             other attributes.
139              
140             sub initialize {
141             my $class = shift;
142             bless { PDL => PDL->null }, $class;
143             }
144              
145             The B method is invoked in a variety of places. For
146             instance, it's called in B, which due to B's
147             inheritance scheme will be called by B's constructor:
148              
149             $mypdl = MyPDL->new( required_attr => 2 );
150              
151             It's also called when B needs to create an object to receive
152             the results of a B operation on a B object:
153              
154             $newpdl = $mypdl + 1;
155              
156             There's one wrinkle, however. B I create an object without
157             any extra attributes (it cannot know which values to give them) so
158             B is called with a I argument, the class name.
159             This means that C<$newpdl> will be an I B object,
160             i.e. C is uninitialized. This can I confuse
161             polymorphic code which operates differently when handed a B or
162             B object.
163              
164             One way out of this dilemma is to have B create a I piddle
165             instead of a B object. B has explicitly indicated it wants to be
166             treated as a normal piddle in B operations (by subclassing from B) so
167             this doesn't break that contract.
168              
169             $newpdl = $mypdl + 1;
170              
171             would result in C<$newpdl> being a normal B object, not a B
172             object.
173              
174             Subclassing from B effects this
175             behavior. B provides a wrapper constructor and
176             an B class method. The constructor ensures returns a
177             properly subclassed hash with the C key, keeping B happy.
178             When B calls the B function it gets a normal B.
179              
180             =head2 Classes without required constructor parameters
181              
182             If your class does I require parameters be passed to the constructor,
183             it is safe to overload the C method to return a fully fledged
184             instance of your class:
185              
186             sub initialize { shift->new() }
187              
188             =head2 Using with Class Frameworks
189              
190             The L shows how to use B with various
191             class frameworks. The key differentiation between frameworks is
192             whether or not they will call a superclass's constructor. B
193             always calls it, B calls it only if it inherits from
194             B, and B and B
195             never will call the superclass' constructor.
196              
197             =begin pod_coverage
198              
199             =head3 initialize
200              
201             =head3 new
202              
203             =end pod_coverage
204              
205             =head1 BUGS AND LIMITATIONS
206              
207             Please report any bugs or feature requests to
208             C, or through the web interface at
209             L.
210              
211             =head1 AUTHOR
212              
213             Diab Jerius
214              
215             =head1 COPYRIGHT AND LICENSE
216              
217             This software is Copyright (c) 2016 by Smithsonian Astrophysical Observatory.
218              
219             This is free software, licensed under:
220              
221             The GNU General Public License, Version 3, June 2007
222              
223             =cut
224              
225             __END__