NAME
   Pony::Object - An object system.

OVERVIEW
   If you wanna protected methods, abstract classes and other stuff like
   with, you may use Pony::Object. Also Pony::Objects are strict and
   modern.

SYNOPSIS
     # Class: MyArticle (Example)
     #   Abstract class for articles.

     package MyArticle;
     use Pony::Object qw(-abstract :exceptions);
     use MyArticle::Exception::IO; # Based on Pony::Object::Throwable class.

       protected date => undef;
       protected authors => [];
       public title => '';
       public text => '';


       # Function: init
       #   Constructor.
       #
       # Parameters:
       #   date - Int
       #   authors - ArrayRef

       sub init : Public
         {
           my $this = shift;
           ($this->date, $this->authors) = @_;
         }


       # Function: getDate
       #   Get formatted date.
       #
       # Returns:
       #   Str

       sub getDate : Public
         {
           my $this = shift;
           return $this->dateFormat($this->date);
         }


       # Function: dateFormat
       #   Convert Unix time to good looking string. Not implemented.
       #
       # Parameters:
       #   date - Int
       #
       # Returns:
       #   String

       sub dateFormat : Abstract;


       # Function: fromPdf
       #   Trying to create article from pdf file.
       #
       # Parameters:
       #   file - Str - pdf file.

       sub fromPdf : Public
         {
           my $this = shift;
           my $file = shift;

           try {
             open F, $file or
               throw MyArticle::Exception::IO(action => "read", file => $file);

             # do smth

             close F;
           } catch {
             my $e = shift; # get exception object

             if ($e->isa('MyArticle::Exception::IO')) {
               # handler for MyArticle::Exception::IO exceptions
             }
           };
         }

     1;

Methods and properties
 has
   Keyword "has" declares new property. You also can define methods via
   "has".

     package News;
     use Pony::Object;

       # Properties:
       has 'title';
       has text => '';
       has authors => [ qw/Alice Bob/ ];

       # Methods:
       has printTitle => sub {
         my $this = shift;
         say $this->title;
       };

       sub printAuthors
         {
           my $this = shift;
           print @{$this->authors};
         }
     1;



     package main;
     use News;
     my $news = new News;
     $news->printAuthors();
     $news->title = 'Sensation!'; # Yep, you can assign property's value via "=".
     $news->printTitle();

 new
   Pony::Objects hasn't method "new". In fact, of course they has. But
   "new" is an internal function, so you should not use "new" as name of
   method.

   Instead of this Pony::Objects has "init" methods, where you can write
   the same, what you wish write in "new". "init" is after-hook for "new".

     package News;
     use Pony::Object;

       has title => undef;
       has lower => undef;

       sub init
         {
           my $this = shift;
           $this->title = shift;
           $this->lower = lc $this->title;
         }

     1;



     package main;
     use News;
     my $news = new News('Big Event!');
     print $news->lower;

 public, protected, private properties
   You can use "has" keyword to define property. If your variable starts
   with "_", variable becomes protected. "__" for private.

     package News;
     use Pony::Object;

       has text => '';
       has __authors => [ qw/Alice Bob/ ];

       sub getAuthorString
         {
           my $this = shift;
           return join(' ', @{$this->__authors});
         }

     1;



     package main;
     use News;
     my $news = new News;
     say $news->getAuthorString();

   The same but with keywords "public", "protected" and "private".

     package News;
     use Pony::Object;

       public text => '';
       private authors => [ qw/Alice Bob/ ];

       sub getAuthorString
         {
           my $this = shift;
           return join(' ', @{$this->authors});
         }

     1;



     package main;
     use News;
     my $news = new News;
     say $news->getAuthorString();

 Public, Protected, Private methods
   Use attributes "Public", "Private" and "Protected" to define method's
   access type.

     package News;
     use Pony::Object;

       public text => '';
       private authors => [ qw/Alice Bob/ ];

       sub getAuthorString : Public
         {
           return shift->joinAuthors(', ');
         }

       sub joinAuthors : Private
         {
           my $this = shift;
           my $delim = shift;

           return join( $delim, @{$this->authors} );
         }

     1;



     package main;
     use News;
     my $news = new News;
     say $news->getAuthorString();

 Static properties
   Just say ""static"" and property will the same in all objects of class.

     package News;
     use Pony::Object;

       public static 'default_publisher' => 'Georgy';
       public 'publisher';

       sub init : Public
         {
           my $this = shift;
           $this->publisher = $this->default_publisher;
         }

     1;



     package main;
     use News;

     my $n1 = new News;
     $n1->default_publisher = 'Bazhukov';
     my $n2 = new News;
     print $n1->publisher; # "Georgy"
     print $n2->publisher; # "Bazhukov"

Default methods
 toHash or to_h
   Get object's data structure and return this as a hash.

     package News;
     use Pony::Object;

       has title => 'World';
       has text => 'Hello';

     1;



     package main;
     use News;
     my $news = new News;
     print $news->toHash()->{text};
     print $news->to_h()->{title};

 dump
   Shows object's current struct.

     package News;
     use Pony::Object;

       has title => 'World';
       has text => 'Hello';

     1;



     package main;
     use News;
     my $news = new News;
     $news->text = 'Hi';
     print $news->dump();

   Returns

     $VAR1 = bless( {
       'text' => 'Hi',
       'title' => 'World'
     }, 'News' );

 Without Objects
   If you like functions "say", "dump", "try"/"catch", you can use them
   without creating object. Use ":noobject" option to enable them but do
   not create object/making class.

     use Pony::Object qw/:noobject :try/;

     my $a = {deep => [{deep => ['structure']}]};
     say dump $a;

     my $data = try {
       local $/;
       open my $fh, './some/file' or die;
       my $slurp = <$fh>;
       close $fh;
       return $slurp;
     } catch {
       return '';
     };

     say "\$data: $data";

Classes
 Inheritance
   You can define base classes via "use" params. For example, "use
   Pony::Object 'Base::Class';"

     package BaseCar;
     use Pony::Object;

       public speed => 0;
       protected model => "Base Car";

       sub get_status_line : Public
         {
           my $this = shift;
           my $status = ($this->speed ? "Moving" : "Stopped");
           return $this->model . " " . $status;
         }

     1;



     package MyCar;
     # extends BaseCar
     use Pony::Object qw/BaseCar/;

       protected model => "My Car";
       protected color => undef;

       sub set_color : Public
         {
           my $this = shift;
           ($this->color) = @_;
         }

     1;



     package main;
     use MyCar;
     my $car = new MyCar;
     $car->speed = 20;
     $car->set_color("White");
     print $car->get_status_line();
     # "My Car Moving"

 Singletons
   Pony::Object has simple syntax for singletons . You can declare this via
   "use" param;

     package Notes;
     use Pony::Object 'singleton';

       protected list => [];

       sub add : Public
         {
           my $this = shift;
           push @{ $this->list }, @_;
         }

       sub show : Public
         {
           my $this = shift;
           say for @{$this->list};
         }

       sub flush : Public
         {
           my $this = shift;
           $this->list = [];
         }

     1;



     package main;
     use Notes;

     my $n1 = new Notes;
     my $n2 = new Notes;

     $n1->add(qw/eat sleep/);
     $n1->add('Meet with Mary at 8 o`clock');

     $n2->flush;

     $n1->show();  # Print nothing.
                   # Em... When I should meet Mary?

 Abstract methods and classes
   You can use abstract methods and classes follows way:

     # Let's define simple interface for texts.
     package Text::Interface;
     use Pony::Object -abstract; # Use 'abstract' or '-abstract'
                                 # params to define abstract class.

       sub getText : Abstract; # Use 'Abstract' attribute to
       sub setText : Abstract; # define abstract method.

     1;



     # Now we can define base class for texts.
     # It's abstract too but now it has some code.
     package Text::Base;
     use Pony::Object qw/abstract Text::Interface/;

       protected text => '';

       sub getText : Public
         {
           my $this = shift;
           return $this->text;
         }

     1;



     # In the end we can write Text class.
     package Text;
     use Pony::Object 'Text::Base';

       sub setText : Public
         {
           my $this = shift;
           $this->text = shift;
         }

     1;



     # Main file.
     package main;
     use Text;
     use Text::Base;

     my $textBase = new Text::Base;  # Raises an error!

     my $text = new Text;
     $text->setText('some text');
     print $text->getText();   # Returns 'some text';

   Don't forget, that perl looking for functions from left to right in list
   of inheritance. You should define abstract classes in the end of
   Pony::Object param list.

 Exceptions
   See Pony::Object::Throwable.

 Inside
  ALL
   If you wanna get all default values of Pony::Object-based class, you can
   call "ALL" method. I don't know why you need them, but you can.

     package News;
     use Pony::Object;

       has 'title';
       has text => '';
       has authors => [ qw/Alice Bob/ ];

     1;



     package main;
     my $news = new News;
     print for keys %{ $news->ALL() };

  META
   One more internal method. It provides access to special hash %META. You
   can use this for Pony::Object introspection. It can be changed in next
   versions.

     my $news = new News;
     say dump $news->META;

  $Pony::Object::DEFAULT
   This is a global variable. It defines default Pony::Object's params. For
   example you can set "$Pony::Object::DEFAULT-"{''}->{withExceptions} = 1>
   to enable exceptions (try, catch, finally blocks) by default. Use it
   carefully.

     # Startup script
     ...
     use Pony::Object;

     BEGIN {
       # Use exceptions by default.
       $Pony::Object::DEFAULT->{''}->{withExceptions} = 1;
       # All classes will extends Default::Base.
       $Pony::Object::DEFAULT->{''}->{baseClass} = [qw/Default::Base/];
       # All classes in namespace "Default::NoBase" will not.
       $Pony::Object::DEFAULT->{'Default::NoBase'}->{baseClass} = [];
     }
     ...

   One more example:

     # Startup script
     ...
     use Pony::Object;

     BEGIN {
       $Pony::Object::DEFAULT->{'My::Awesome::Project'} = {
         withExceptions => 1,
         baseClass => [],
       };

       $Pony::Object::DEFAULT->{'My::Awesome::Project::Model'} = {
         withExceptions => 1,
         baseClass => [qw/My::Awesome::Project::Model::Abstract/],
       };
     }
     ...

SEE
   Git <https://github.com/h15/pony-object>

COPYRIGHT AND LICENSE
   Copyright (C) 2011 - 2013, Georgy Bazhukov.

   This program is free software, you can redistribute it and/or modify it
   under the terms of the Artistic License version 2.0.