{
    "content": [
        {
            "type": "text",
            "text": "# Moose::Cookbook::Basics::BankAccount_MethodModifiersAndSubclassing (info)\n\n## NAME\n\nMoose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing - Demonstrates the use of method modifiers in a subclass\n\n## SYNOPSIS\n\npackage BankAccount;\nuse Moose;\nhas 'balance' => ( isa => 'Int', is => 'rw', default => 0 );\nsub deposit {\nmy ( $self, $amount ) = @;\n$self->balance( $self->balance + $amount );\n}\nsub withdraw {\nmy ( $self, $amount ) = @;\nmy $currentbalance = $self->balance();\n( $currentbalance >= $amount )\n|| confess \"Account overdrawn\";\n$self->balance( $currentbalance - $amount );\n}\npackage CheckingAccount;\nuse Moose;\nextends 'BankAccount';\nhas 'overdraftaccount' => ( isa => 'BankAccount', is => 'rw' );\nbefore 'withdraw' => sub {\nmy ( $self, $amount ) = @;\nmy $overdraftamount = $amount - $self->balance();\nif ( $self->overdraftaccount && $overdraftamount > 0 ) {\n$self->overdraftaccount->withdraw($overdraftamount);\n$self->deposit($overdraftamount);\n}\n};\n\n## DESCRIPTION\n\nThe first recipe demonstrated how to build very basic Moose classes,\nfocusing on creating and manipulating attributes. The objects in that\nrecipe were very data-oriented, and did not have much in the way of\nbehavior (i.e. methods). In this recipe, we expand upon the concepts\nfrom the first recipe to include some real behavior. In particular, we\nshow how you can use a method modifier to implement new behavior for a\nmethod.\n\n## Sections\n\n- **Moose::Moose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing(3pm)**\n- **NAME**\n- **VERSION**\n- **SYNOPSIS**\n- **DESCRIPTION**\n- **CONCLUSION**\n- **FOOTNOTES**\n- **ACKNOWLEDGMENT**\n- **AUTHORS**\n- **COPYRIGHT AND LICENSE**\n\nUse structuredContent.sections for detailed options, examples, and full documentation.\n"
        }
    ],
    "structuredContent": {
        "command": "Moose::Cookbook::Basics::BankAccount_MethodModifiersAndSubclassing",
        "section": "",
        "mode": "info",
        "summary": "Moose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing - Demonstrates the use of method modifiers in a subclass",
        "synopsis": "package BankAccount;\nuse Moose;\nhas 'balance' => ( isa => 'Int', is => 'rw', default => 0 );\nsub deposit {\nmy ( $self, $amount ) = @;\n$self->balance( $self->balance + $amount );\n}\nsub withdraw {\nmy ( $self, $amount ) = @;\nmy $currentbalance = $self->balance();\n( $currentbalance >= $amount )\n|| confess \"Account overdrawn\";\n$self->balance( $currentbalance - $amount );\n}\npackage CheckingAccount;\nuse Moose;\nextends 'BankAccount';\nhas 'overdraftaccount' => ( isa => 'BankAccount', is => 'rw' );\nbefore 'withdraw' => sub {\nmy ( $self, $amount ) = @;\nmy $overdraftamount = $amount - $self->balance();\nif ( $self->overdraftaccount && $overdraftamount > 0 ) {\n$self->overdraftaccount->withdraw($overdraftamount);\n$self->deposit($overdraftamount);\n}\n};",
        "tldr_summary": null,
        "tldr_examples": [],
        "tldr_source": null,
        "flags": [],
        "examples": [],
        "see_also": [],
        "section_outline": [
            {
                "name": "Moose::Moose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing(3pm)",
                "lines": 1,
                "subsections": []
            },
            {
                "name": "NAME",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "VERSION",
                "lines": 2,
                "subsections": []
            },
            {
                "name": "SYNOPSIS",
                "lines": 34,
                "subsections": []
            },
            {
                "name": "DESCRIPTION",
                "lines": 114,
                "subsections": []
            },
            {
                "name": "CONCLUSION",
                "lines": 3,
                "subsections": []
            },
            {
                "name": "FOOTNOTES",
                "lines": 29,
                "subsections": []
            },
            {
                "name": "ACKNOWLEDGMENT",
                "lines": 5,
                "subsections": []
            },
            {
                "name": "AUTHORS",
                "lines": 20,
                "subsections": []
            },
            {
                "name": "COPYRIGHT AND LICENSE",
                "lines": 6,
                "subsections": []
            }
        ],
        "sections": {
            "Moose::Moose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing(3pm)": {
                "content": "",
                "subsections": []
            },
            "NAME": {
                "content": "Moose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing -\nDemonstrates the use of method modifiers in a subclass\n",
                "subsections": []
            },
            "VERSION": {
                "content": "version 2.2200\n",
                "subsections": []
            },
            "SYNOPSIS": {
                "content": "package BankAccount;\nuse Moose;\n\nhas 'balance' => ( isa => 'Int', is => 'rw', default => 0 );\n\nsub deposit {\nmy ( $self, $amount ) = @;\n$self->balance( $self->balance + $amount );\n}\n\nsub withdraw {\nmy ( $self, $amount ) = @;\nmy $currentbalance = $self->balance();\n( $currentbalance >= $amount )\n|| confess \"Account overdrawn\";\n$self->balance( $currentbalance - $amount );\n}\n\npackage CheckingAccount;\nuse Moose;\n\nextends 'BankAccount';\n\nhas 'overdraftaccount' => ( isa => 'BankAccount', is => 'rw' );\n\nbefore 'withdraw' => sub {\nmy ( $self, $amount ) = @;\nmy $overdraftamount = $amount - $self->balance();\nif ( $self->overdraftaccount && $overdraftamount > 0 ) {\n$self->overdraftaccount->withdraw($overdraftamount);\n$self->deposit($overdraftamount);\n}\n};\n",
                "subsections": []
            },
            "DESCRIPTION": {
                "content": "The first recipe demonstrated how to build very basic Moose classes,\nfocusing on creating and manipulating attributes. The objects in that\nrecipe were very data-oriented, and did not have much in the way of\nbehavior (i.e. methods). In this recipe, we expand upon the concepts\nfrom the first recipe to include some real behavior. In particular, we\nshow how you can use a method modifier to implement new behavior for a\nmethod.\n\nThe classes in the SYNOPSIS show two kinds of bank account. A simple\nbank account has one attribute, the balance, and two behaviors,\ndepositing and withdrawing money.\n\nWe then extend the basic bank account in the CheckingAccount class.\nThis class adds another attribute, an overdraft account. It also adds\noverdraft protection to the withdraw method. If you try to withdraw\nmore than you have, the checking account attempts to reconcile the\ndifference by withdrawing money from the overdraft account. (1)\n\nThe first class, BankAccount, introduces a new attribute feature, a\ndefault value:\n\nhas 'balance' => ( isa => 'Int', is => 'rw', default => 0 );\n\nThis says that a BankAccount has a \"balance\" attribute, which has an\n\"Int\" type constraint, a read/write accessor, and a default value of 0.\nThis means that every instance of BankAccount that is created will have\nits \"balance\" slot initialized to 0, unless some other value is\nprovided to the constructor.\n\nThe \"deposit\" and \"withdraw\" methods should be fairly self-explanatory,\nas they are just plain old Perl 5 OO. (2)\n\nAs you know from the first recipe, the keyword \"extends\" sets a class's\nsuperclass. Here we see that CheckingAccount \"extends\" BankAccount. The\nnext line introduces yet another new attribute feature, class-based\ntype constraints:\n\nhas 'overdraftaccount' => ( isa => 'BankAccount', is => 'rw' );\n\nUp until now, we have only seen the \"Int\" type constraint, which (as we\nsaw in the first recipe) is a builtin type constraint. The\n\"BankAccount\" type constraint is new, and was actually defined the\nmoment we created the BankAccount class itself. In fact, Moose creates\na corresponding type constraint for every class in your program (3).\n\nThis means that in the first recipe, constraints for both \"Point\" and\n\"Point3D\" were created. In this recipe, both \"BankAccount\" and\n\"CheckingAccount\" type constraints are created automatically. Moose\ndoes this as a convenience so that your classes and type constraint can\nbe kept in sync with one another. In short, Moose makes sure that it\nwill just DWIM (4).\n\nIn CheckingAccount, we see another method modifier, the \"before\"\nmodifier.\n\nbefore 'withdraw' => sub {\nmy ( $self, $amount ) = @;\nmy $overdraftamount = $amount - $self->balance();\nif ( $self->overdraftaccount && $overdraftamount > 0 ) {\n$self->overdraftaccount->withdraw($overdraftamount);\n$self->deposit($overdraftamount);\n}\n};\n\nJust as with the \"after\" modifier from the first recipe, Moose will\nhandle calling the superclass method (in this case\n\"BankAccount->withdraw\").\n\nThe \"before\" modifier will (obviously) run before the code from the\nsuperclass is run. Here, \"before\" modifier implements overdraft\nprotection by first checking if there are available funds in the\nchecking account. If not (and if there is an overdraft account\navailable), it transfers the amount needed into the checking account\n(5).\n\nAs with the method modifier in the first recipe, we could use \"SUPER::\"\nto get the same effect:\n\nsub withdraw {\nmy ( $self, $amount ) = @;\nmy $overdraftamount = $amount - $self->balance();\nif ( $self->overdraftaccount && $overdraftamount > 0 ) {\n$self->overdraftaccount->withdraw($overdraftamount);\n$self->deposit($overdraftamount);\n}\n$self->SUPER::withdraw($amount);\n}\n\nThe benefit of taking the method modifier approach is we do not need to\nremember to call \"SUPER::withdraw\" and pass it the $amount argument\nwhen writing \"CheckingAccount->withdraw\".\n\nThis is actually more than just a convenience for forgetful\nprogrammers. Using method modifiers helps isolate subclasses from\nchanges in the superclasses. For instance, if BankAccount->withdraw\nwere to add an additional argument of some kind, the version of\nCheckingAccount->withdraw which uses \"SUPER::withdraw\" would not pass\nthat extra argument correctly, whereas the method modifier version\nwould automatically pass along all arguments correctly.\n\nJust as with the first recipe, object instantiation uses the \"new\"\nmethod, which accepts named parameters.\n\nmy $savingsaccount = BankAccount->new( balance => 250 );\n\nmy $checkingaccount = CheckingAccount->new(\nbalance           => 100,\noverdraftaccount => $savingsaccount,\n);\n\nAnd as with the first recipe, a more in-depth example can be found in\nthe t/recipes/basicsbankaccountmethodmodifiersandsubclassing.t test\nfile.\n",
                "subsections": []
            },
            "CONCLUSION": {
                "content": "This recipe expanded on the basic concepts from the first recipe with a\nmore \"real world\" use case.\n",
                "subsections": []
            },
            "FOOTNOTES": {
                "content": "(1) If you're paying close attention, you might realize that there's a\ncircular loop waiting to happen here. A smarter example would have\nto make sure that we don't accidentally create a loop between the\nchecking account and its overdraft account.\n\n(2) Note that for simple methods like these, which just manipulate some\nsingle piece of data, it is often not necessary to write them at\nall.  For instance, \"deposit\" could be implemented via the \"inc\"\nnative delegation for counters - see\nMoose::Meta::Attribute::Native::Trait::Counter for more specifics,\nand Moose::Meta::Attribute::Native for a broader overview.\n\n(3) In reality, this creation is sensitive to the order in which\nmodules are loaded. In more complicated cases, you may find that\nyou need to explicitly declare a class type before the\ncorresponding class is loaded.\n\n(4) Moose does not attempt to encode a class's is-a relationships\nwithin the type constraint hierarchy. Instead, Moose just considers\nthe class type constraint to be a subtype of \"Object\", and\nspecializes the constraint check to allow for subclasses. This\nmeans that an instance of CheckingAccount will pass a \"BankAccount\"\ntype constraint successfully. For more details, please refer to the\nMoose::Util::TypeConstraints documentation.\n\n(5) If the overdraft account does not have the amount needed, it will\nthrow an error. Of course, the overdraft account could also have\noverdraft protection. See note 1.\n",
                "subsections": []
            },
            "ACKNOWLEDGMENT": {
                "content": "The BankAccount example in this recipe is directly taken from the\nexamples in this chapter of \"Practical Common Lisp\":\n\n<http://www.gigamonkeys.com/book/object-reorientation-generic-functions.html>\n",
                "subsections": []
            },
            "AUTHORS": {
                "content": "o   Stevan Little <stevan@cpan.org>\n\no   Dave Rolsky <autarch@urth.org>\n\no   Jesse Luehrs <doy@cpan.org>\n\no   Shawn M Moore <sartak@cpan.org>\n\no    ' (Yuval Kogman) <nothingmuch@woobling.org>\n\no   Karen Etheridge <ether@cpan.org>\n\no   Florian Ragwitz <rafl@debian.org>\n\no   Hans Dieter Pearcey <hdp@cpan.org>\n\no   Chris Prather <chris@prather.org>\n\no   Matt S Trout <mstrout@cpan.org>\n",
                "subsections": []
            },
            "COPYRIGHT AND LICENSE": {
                "content": "This software is copyright (c) 2006 by Infinity Interactive, Inc.\n\nThis is free software; you can redistribute it and/or modify it under\nthe same terms as the Perl 5 programming language system itself.\n\nperl v5Moose::Cookbook::Basics::BankAccountMethodModifiersAndSubclassing(3pm)",
                "subsections": []
            }
        }
    }
}