File Coverage

blib/lib/Object/Simple.pm
Criterion Covered Total %
statement 153 189 80.9
branch 71 106 66.9
condition 7 9 77.7
subroutine 16 16 100.0
pod 2 4 50.0
total 249 324 76.8


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