File Coverage

blib/lib/Object/Simple.pm
Criterion Covered Total %
statement 146 180 81.1
branch 69 102 67.6
condition 7 9 77.7
subroutine 14 14 100.0
pod 2 2 100.0
total 238 307 77.5


line stmt bran cond sub pod time code
1             package Object::Simple;
2              
3             our $VERSION = '3.19';
4              
5 1     1   14411 use strict;
  1         1  
  1         35  
6 1     1   2 use warnings;
  1         1  
  1         18  
7 1     1   4 use Scalar::Util ();
  1         4  
  1         12  
8              
9 1     1   2 no warnings 'redefine';
  1         1  
  1         27  
10              
11 1     1   3 use Carp ();
  1         1  
  1         115  
12              
13             sub import {
14 12     12   639 my $class = shift;
15            
16 12 100       307 return unless @_;
17              
18             # Caller
19 9         12 my $caller = caller;
20            
21             # No export syntax
22 9         6 my $no_export_syntax;
23 9 100       8 unless (grep { $_[0] eq $_ } qw/new attr/) {
  18         34  
24 8         7 $no_export_syntax = 1;
25             }
26            
27             # Inheritance
28 9 100       10 if ($no_export_syntax) {
29 8         8 my $arg1 = shift;
30 8         5 my $arg2 = shift;
31            
32 8         8 my $base_class;
33 8 50       13 if (defined $arg1) {
34             # Option
35 8 100       20 if ($arg1 =~ /^-/) {
36 7 100       10 if ($arg1 eq '-base') {
37 6 100       10 if (defined $arg2) {
38 2         2 $base_class = $arg2;
39             }
40             }
41             else {
42 1         123 Carp::croak "'$arg1' is invalid option(Object::Simple::import())";
43             }
44             }
45             # Base class
46             else {
47 1         2 $base_class = $arg1;
48             }
49             }
50            
51             # Export has function
52 1     1   3 no strict 'refs';
  1         1  
  1         26  
53 1     1   3 no warnings 'redefine';
  1         1  
  1         163  
54 7     4   17 *{"${caller}::has"} = sub { attr($caller, @_) };
  7         19  
  4         13  
55            
56             # Inheritance
57 7 100       10 if ($base_class) {
58 3         3 my $base_class_path = $base_class;
59 3         7 $base_class_path =~ s/::|'/\//g;
60 3         203 require "$base_class_path.pm";
61 3         6 @{"${caller}::ISA"} = ($base_class);
  3         40  
62             }
63 4         16 else { @{"${caller}::ISA"} = ($class) }
  4         29  
64            
65             # strict!
66 7         21 strict->import;
67 7         369 warnings->import;
68             }
69            
70             # Export methods
71             else {
72 1         2 my @methods = @_;
73            
74             # Exports
75 1         1 my %exports = map { $_ => 1 } qw/new attr/;
  2         4  
76            
77             # Export methods
78 1         2 for my $method (@methods) {
79              
80             # Can be Exported?
81             Carp::croak("Cannot export '$method'.")
82 2 50       4 unless $exports{$method};
83              
84 2         15 warn "function exporting of $method is DEPRECATED(Object::Simple)";
85            
86             # Export
87 1     1   4 no strict 'refs';
  1         1  
  1         314  
88 2         11 *{"${caller}::$method"} = \&{"$method"};
  2         1506  
  2         3  
89             }
90             }
91             }
92              
93             sub new {
94 24     24 1 7470 my $class = shift;
95 24 100 66     136 bless @_ ? @_ > 1 ? {@_} : {%{$_[0]}} : {}, ref $class || $class;
  4 100       23  
96             }
97              
98             sub attr {
99 14     14 1 1452 my ($self, @args) = @_;
100            
101 14   66     45 my $class = ref $self || $self;
102            
103             # Fix argument
104 14 100       56 unshift @args, (shift @args, undef) if @args % 2;
105            
106 14         29 for (my $i = 0; $i < @args; $i += 2) {
107            
108 17 100       24 if ($i == 2) {
109 2         27 warn "The syntax of multiple key-value arguments is DEPRECATED(Object::Simple::has or Object::Simple::attr)";
110             }
111            
112             # Attribute name
113 17         27 my $attrs = $args[$i];
114 17 100       49 $attrs = [$attrs] unless ref $attrs eq 'ARRAY';
115            
116             # Default
117 17         33 my $default = $args[$i + 1];
118            
119 17         23 for my $attr (@$attrs) {
120              
121 20 50       62 Carp::croak qq{Attribute "$attr" invalid} unless $attr =~ /^[a-zA-Z_]\w*$/;
122              
123             # Header (check arguments)
124 20         32 my $code = "*{\"${class}::$attr\"} = sub {\n if (\@_ == 1) {\n";
125              
126             # No default value (return value)
127 20 100       27 unless (defined $default) { $code .= " return \$_[0]{'$attr'};" }
  7         11  
128              
129             # Default value
130             else {
131              
132 13 100 100     258 Carp::croak "Default has to be a code reference or constant value (${class}::$attr)"
133             if ref $default && ref $default ne 'CODE';
134              
135             # Return value
136 12         15 $code .= " return \$_[0]{'$attr'} if exists \$_[0]{'$attr'};\n";
137              
138             # Return default value
139 12         9 $code .= " return \$_[0]{'$attr'} = ";
140 12 100       19 $code .= ref $default eq 'CODE' ? '$default->($_[0]);' : '$default;';
141             }
142              
143             # Store value
144 19         18 $code .= "\n }\n \$_[0]{'$attr'} = \$_[1];\n";
145              
146             # Footer (return invocant)
147 19         15 $code .= " \$_[0];\n}";
148              
149             # We compile custom attribute code for speed
150 1     1   4 no strict 'refs';
  1         0  
  1         152  
151 19 50       30 warn "-- Attribute $attr in $class\n$code\n\n" if $ENV{OBJECT_SIMPLE_DEBUG};
152 19 50   2   1783 Carp::croak "Object::Simple error: $@" unless eval "$code;1";
  2 50       7  
  2 50       6  
  2 50       8  
  0 50       0  
  0 100       0  
  2 50       6  
  2 50       5  
  2 0       6  
  0 50       0  
  0 50       0  
  2 100       6  
  1 50       3  
  1 50       3  
  1 50       2  
  1 50       264  
  1 0       3  
  1 100       3  
  0 100       0  
  0 100       0  
  0 50       0  
  0 50       0  
  0 50       0  
  0 50       0  
  1 50       255  
  1 50       3  
  1 0       4  
  0 100       0  
  0 50       0  
  11 50       974  
  8 50       24  
  3 50       7  
  3         5  
  1         4  
  1         4  
  1         4  
  0         0  
  0         0  
  3         12  
  3         5  
  3         12  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  5         87  
  3         8  
  2         7  
  2         4  
  2         3  
  2         43  
  1         4  
  1         2  
  1         2  
  1         356  
  1         3  
  1         4  
  0         0  
  0         0  
  6         174  
  6         22  
  6         21  
  0         0  
  0         0  
  6         17  
  6         13  
  6         16  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  0         0  
  2         40  
  1         5  
  1         26  
  1         2  
  1         4  
  1         3  
  1         4  
  0         0  
  0         0  
  1         4  
  1         3  
  1         3  
  0            
  0            
153             }
154             }
155             }
156              
157             =head1 NAME
158              
159             Object::Simple - Simplest class builder, Mojo::Base porting, fast and less memory
160              
161             =over
162              
163             =item *
164              
165             B. All you learn is only C function!
166              
167             =item *
168              
169             B. Do you like L? If so, this is good choices!
170              
171             =item *
172              
173             B. Fast C and accessor method. Memory saving implementation.
174              
175             =back
176              
177             =head1 SYNOPSIS
178              
179             package SomeClass;
180             use Object::Simple -base;
181            
182             # Create accessor
183             has 'foo';
184            
185             # Create accessor with default value
186             has foo => 1;
187             has foo => sub { [] };
188             has foo => sub { {} };
189             has foo => sub { OtherClass->new };
190            
191             # Create accessors at once
192             has ['foo', 'bar', 'baz'];
193             has ['foo', 'bar', 'baz'] => 0;
194            
195             Create object.
196              
197             # Create a new object
198             my $obj = SomeClass->new;
199             my $obj = SomeClass->new(foo => 1, bar => 2);
200             my $obj = SomeClass->new({foo => 1, bar => 2});
201            
202             # Set and get value
203             my $foo = $obj->foo;
204             $obj->foo(1);
205            
206             # Setter can be chained
207             $obj->foo(1)->bar(2);
208              
209             Inheritance
210            
211             package Foo;
212             use Object::Simple -base;
213            
214             # Bar inherit Foo
215             package Bar;
216             use Object::Simple 'Foo';
217              
218             =head1 DESCRIPTION
219              
220             Object::Simple is B class builder. All you learn is only C function.
221             You can learn all features of L in B. There is nothing difficult.
222              
223             Do you like L? In fact, Object::Simple is L porting. Mojo::Base is basic class builder in Mojolicious project.
224             If you like Mojolicious, this is good choice. If you have known Mojo::Base, you learn nothing.
225              
226             C and accessor method is B. Implementation is pure perl and plain old hash-base object.
227             Memory is saved. Extra objects is not created at all. Very light-weight object-oriented module.
228              
229             Comparison with L
230              
231             Class::Accessor::Fast is simple, but lack often used features.
232             C method can't receive hash arguments.
233             Default value can't be specified.
234             If multiple values is set through the accessor,
235             its value is converted to array reference without warnings.
236              
237             Comparison with L
238              
239             Moose has very complex syntax and depend on much many modules.
240             You have to learn many things to do object-oriented programing.
241             Understanding source code is difficult.
242             Compile-time is very slow and memory usage is very large.
243             Execution speed is not fast.
244             For simple OO, Moose is overkill.
245             L is improved in this point.
246              
247             =head1 TUTORIAL
248              
249             =head2 1. Create class and accessor
250              
251             At first, you create class.
252              
253             package SomeClass;
254             use Object::Simple -base;
255              
256             By using C<-base> option, SomeClass inherit Object::Simple and import C method.
257              
258             L have C method. C method is constructor.
259             C method can receive hash or hash reference.
260            
261             my $obj = SomeClass->new;
262             my $obj = SomeClass->new(foo => 1, bar => 2);
263             my $obj = SomeClass->new({foo => 1, bar => 2});
264              
265             Create accessor by using C function.
266              
267             has 'foo';
268              
269             If you create accessor, you can set or get value
270              
271             # Set value
272             $obj->foo(1);
273            
274             # Get value
275             my $foo = $obj->foo;
276              
277             Setter can be chained.
278              
279             $obj->foo(1)->bar(2);
280              
281             You can define default value.
282              
283             has foo => 1;
284              
285             If C value is not exists, default value is used.
286              
287             my $foo_default = $obj->foo;
288              
289             If you want to use reference or object as default value,
290             default value must be surrounded by code reference.
291             the return value become default value.
292              
293             has foo => sub { [] };
294             has foo => sub { {} };
295             has foo => sub { SomeClass->new };
296              
297             You can create multiple accessors at once.
298              
299             has ['foo', 'bar', 'baz'];
300             has ['foo', 'bar', 'baz'] => 0;
301              
302             =head2 2. Override method
303              
304             Method can be overridden.
305              
306             B
307              
308             Initialize the object
309              
310             sub new {
311             my $self = shift->SUPER::new(@_);
312            
313             # Initialization
314            
315             return $self;
316             }
317              
318             B
319              
320             Change arguments of C.
321            
322             sub new {
323             my $self = shift;
324            
325             $self->SUPER::new(x => $_[0], y => $_[1]);
326            
327             return $self;
328             }
329              
330             You can pass array to C method.
331              
332             my $point = Point->new(4, 5);
333              
334             =head2 3. Examples - class, accessor, inheritance and method overriding
335              
336             I introduce L example.
337              
338             Point class: two accessor C and C,
339             and C method to set C and C to 0.
340              
341             package Point;
342             use Object::Simple -base;
343              
344             has x => 0;
345             has y => 0;
346            
347             sub clear {
348             my $self = shift;
349            
350             $self->x(0);
351             $self->y(0);
352             }
353              
354             Use Point class.
355              
356             use Point;
357             my $point = Point->new(x => 3, y => 5);
358             print $point->x;
359             $point->y(9);
360             $point->clear;
361              
362             Point3D class: Point3D inherit Point class.
363             Point3D class has C accessor in addition to C and C.
364             C method is overridden to clear C, C and C.
365              
366             package Point3D;
367             use Object::Simple 'Point';
368            
369             has z => 0;
370            
371             sub clear {
372             my $self = shift;
373            
374             $self->SUPER::clear;
375            
376             $self->z(0);
377             }
378              
379             Use Point3D class.
380              
381             use Point3D;
382             my $point = Point->new(x => 3, y => 5, z => 8);
383             print $point->z;
384             $point->z(9);
385             $point->clear;
386              
387             =head1 WHAT IS OBJECT-ORIENTED PROGRAMING?
388              
389             I introduce essence of Object-Oriented programing.
390              
391             =head2 1. Inheritance
392              
393             First concept is inheritance.
394             Inheritance means that
395             if Class Q inherit Class P, Class Q call all methods of class P.
396              
397             +---+
398             | P | Base class
399             +---+ have method1 and method2
400             |
401             +---+
402             | Q | Sub class
403             +---+ have method3
404              
405             Class Q inherits Class P,
406             Q can call all methods of P in addition to methods of Q.
407              
408             In other words, Q can call
409             C, C, and C
410              
411             You can inherit other class by the following way.
412              
413             # P.pm
414             package P;
415             use Object::Simple -base;
416            
417             sub method1 { ... }
418             sub method2 { ... }
419            
420             # Q.pm
421             package Q;
422             use Object::Simple 'P';
423            
424             sub method3 { ... }
425              
426             Perl have useful functions and methods to help Object-Oriented programing.
427              
428             If you know what class the object is belonged to, use C function.
429              
430             my $class = ref $obj;
431              
432             If you know what class the object inherits, use C method.
433              
434             $obj->isa('SomeClass');
435              
436             If you know what method the object(or class) can use, use C method
437              
438             SomeClass->can('method1');
439             $obj->can('method1');
440              
441             =head2 2. Encapsulation
442              
443             Second concept is encapsulation.
444             Encapsulation means that
445             you don't touch internal data directory.
446             You must use public method when you access internal data.
447              
448             Create accessor and use it to keep this rule.
449              
450             my $value = $obj->foo;
451             $obj->foo(1);
452              
453             =head2 3. Polymorphism
454              
455             Third concept is polymorphism.
456             Polymorphism is divided into two concepts,
457             overload and override
458              
459             Perl programmer don't need to care overload.
460             Perl is dynamic type language.
461             Subroutine can receive any value.
462              
463             Override means that you can change method behavior in sub class.
464            
465             # P.pm
466             package P;
467             use Object::Simple -base;
468            
469             sub method1 { return 1 }
470            
471             # Q.pm
472             package Q;
473             use Object::Simple 'P';
474            
475             sub method1 { return 2 }
476              
477             P C return 1. Q C return 2.
478             Q C override P C.
479              
480             # P method1 return 1
481             my $obj_a = P->new;
482             $obj_p->method1;
483            
484             # Q method1 return 2
485             my $obj_b = Q->new;
486             $obj_q->method1;
487              
488             If you want to call super class method from sub class,
489             use SUPER pseudo-class.
490              
491             package Q;
492             use Object::Simple 'P';
493            
494             sub method1 {
495             my $self = shift;
496            
497             # Call supper class P method1
498             my $value = $self->SUPER::method1;
499            
500             return 2 + $value;
501             }
502              
503             If you understand three concepts,
504             you have learned Object-Oriented programming primary parts.
505              
506             =head1 FUNCTIONS
507              
508             =head2 has
509              
510             Create accessor.
511            
512             has 'foo';
513             has ['foo', 'bar', 'baz'];
514             has foo => 1;
515             has foo => sub { {} };
516              
517             has ['foo', 'bar', 'baz'];
518             has ['foo', 'bar', 'baz'] => 0;
519              
520             C function receive
521             accessor name and default value.
522             Default value is optional.
523             If you want to create multiple accessors at once,
524             specify accessor names as array reference at first argument.
525              
526             If you want to specify reference or object as default value,
527             it must be code reference
528             not to share the value with other objects.
529              
530             Get and set a value.
531              
532             my $foo = $obj->foo;
533             $obj->foo(1);
534              
535             If a default value is specified and the value is not exists,
536             you can get default value.
537              
538             Setter return invocant. so you can do chained call.
539              
540             $obj->foo(1)->bar(2);
541              
542             =head1 METHODS
543              
544             =head2 new
545              
546             my $obj = Object::Simple->new;
547             my $obj = Object::Simple->new(foo => 1, bar => 2);
548             my $obj = Object::Simple->new({foo => 1, bar => 2});
549              
550             Create a new object. C receive
551             hash or hash reference as arguments.
552              
553             =head2 attr
554              
555             __PACKAGE__->attr('foo');
556             __PACKAGE__->attr(['foo', 'bar', 'baz']);
557             __PACKAGE__->attr(foo => 1);
558             __PACKAGE__->attr(foo => sub { {} });
559              
560             __PACKAGE__->attr(['foo', 'bar', 'baz']);
561             __PACKAGE__->attr(['foo', 'bar', 'baz'] => 0);
562              
563             Create accessor.
564             C method usage is equal to C function.
565              
566             =head1 OPTIONS
567              
568             =head2 -base
569              
570             By using C<-base> option, the class inherit Object::Simple
571             and import C function.
572              
573             package Foo;
574             use Object::Simple -base;
575            
576             has x => 1;
577             has y => 2;
578              
579             strict and warnings is automatically enabled.
580              
581             If you want to inherit class, let's write the following way.
582            
583             # Bar inherit Foo
584             package Bar;
585             use Object::Simple 'Foo';
586              
587             You can also use the following syntax. This is Object::Simple only.
588              
589             # Same as above
590             package Bar;
591             use Object::Simple -base => 'Foo';
592              
593             You can also use C<-base> option in sub class
594             to inherit other class. This is Object::Simple only.
595              
596             # Same as above
597             package Bar;
598             use Foo -base;
599              
600             =head1 FAQ
601              
602             =head2 Really enough object-oriented programing with this few features?
603              
604             Yes, for example, Mojolicious is very big project, but in fact, source code is clean only using single inheritance.
605             Generally speaking, readable source code is build on simple concepts, not complex features.
606              
607             C, C and C methods in L are needed for good object-oriented programming?
608             If you want to use multiple inheritance or role, these methods is needed.
609              
610             But I strongly recommend you use only single inheritance in object-oriented programming. Single inheritance is clean and readable.
611              
612             If you use only single inheritance,
613             You can create custom constructor and call constructors in correct order.
614             and You can create custom destructor and call destructors in correct order,
615              
616             Creating custom constructor is very very easy. There is nothing difficult.
617            
618             # Custom constructor
619             sub new {
620             # At first Call super class constructor. Next do what you want
621             my $self = shift->SUPER::new(@_);
622            
623             # What you want
624            
625             return $self;
626             }
627            
628             # Custom destructor
629             sub DESTROY {
630             my $self = shift;
631            
632             # What you want
633              
634             # At first, do what you want, Next call super class destructor
635             $selft->SUPER::DESTROY;
636            
637             return $self;
638             }
639              
640             =head2 Object::Simple is fastest OO module?
641              
642             No, Object::Simple is B fastest module, but enough fast. If you really need performance, you can access hash value directory.
643              
644             # I want performance in some places. Let's access hash value directory!
645             # Object::Simple is plain old hash-based object
646             $self->{x};
647              
648             =head2 What is benefits comparing with Mojo::Base?
649              
650             =over
651              
652             =item *
653              
654             Support Perl 5.8
655              
656             =item *
657              
658             Installation is very fast because there are a few files.
659              
660             =item *
661              
662             Some people think that my module want not to depend on whole Mojolicious to use Mojo::Base only. Object::Simple satisfy the demand.
663              
664             =head2 Why Object::Simple is different from Mojo::Base in some points?
665              
666             In old days, Object::Simple wasn't Mojo::Base porting. I tried different things.
667              
668             Now, I want Object::Simple to be same as Mojo::Base completely except supporting Perl 5.8.
669              
670             =back
671              
672             =head1 BACKWARDS COMPATIBILITY POLICY
673              
674             If a functionality is DEPRECATED, you can know it by DEPRECATED warnings.
675             You can check all DEPRECATED functionalities by document.
676             DEPRECATED functionality is removed after five years,
677             but if at least one person use the functionality and tell me that thing
678             I extend one year each time he tell me it.
679              
680             EXPERIMENTAL functionality will be changed without warnings.
681              
682             (This policy was changed at 2011/10/22)
683              
684             =head1 DEPRECATED
685              
686             function exporting of C and C method # Will be removed 2021/6/1
687            
688             The syntax of multiple key-value arguments
689             has x => 1, y => 2;
690             __PACAKGE__->attr(x => 1, y => 2);
691             # Will be removed 2021/6/1
692              
693             =head1 BUGS
694              
695             Tell me the bugs
696             by mail(C<< >>) or github L
697              
698             =head1 SUPPORT
699              
700             If you have any questions the documentation might not yet answer, don't hesitate to ask on the mailing list or the official IRC channel
701             #object-simple on irc.perl.org.
702              
703             =head1 AUTHOR
704              
705             Yuki Kimoto(C<< >>)
706              
707             I'm pleasure if you send message for cheer. I can get power by only your messages!
708              
709             =head1 USERS
710              
711             Projects using L.
712              
713             =over 4
714              
715             =item *
716              
717             GitPrep - Portable GitHub system into your own server. L
718              
719             =item *
720              
721             L - DBI extension to execute insert, update, delete, and select easily
722              
723             =item *
724              
725             L - HTML form Validation, simple and good flexibility
726              
727             =back
728              
729             =head1 SEE ALSO
730              
731             CPAN have various class builders. Let's compare it with L.
732              
733             L, L, L, L, L, L.
734              
735             =head1 COPYRIGHT & LICENSE
736              
737             Copyright 2008-2017 Yuki Kimoto, all rights reserved.
738              
739             This program is free software; you can redistribute it and/or modify it
740             under the same terms as Artistic v2.
741              
742             This is same as L licence.
743              
744             =cut
745              
746             1;