{
    "mode": "perldoc",
    "parameter": "Class::C3",
    "section": "",
    "url": "https://www.chedong.com/phpMan.php/perldoc/Class%3A%3AC3/json",
    "generated": "2026-06-09T20:54:23Z",
    "synopsis": "# NOTE - DO NOT USE Class::C3 directly as a user, use MRO::Compat instead!\npackage ClassA;\nuse Class::C3;\nsub hello { 'A::hello' }\npackage ClassB;\nuse base 'ClassA';\nuse Class::C3;\npackage ClassC;\nuse base 'ClassA';\nuse Class::C3;\nsub hello { 'C::hello' }\npackage ClassD;\nuse base ('ClassB', 'ClassC');\nuse Class::C3;\n# Classic Diamond MI pattern\n#    <A>\n#   /   \\\n# <B>   <C>\n#   \\   /\n#    <D>\npackage main;\n# initializez the C3 module\n# (formerly called in INIT)\nClass::C3::initialize();\nprint join ', ' => Class::C3::calculateMRO('ClassD'); # prints ClassD, ClassB, ClassC, ClassA\nprint ClassD->hello(); # prints 'C::hello' instead of the standard p5 'A::hello'\nClassD->can('hello')->();          # can() also works correctly\nUNIVERSAL::can('ClassD', 'hello'); # as does UNIVERSAL::can()",
    "sections": {
        "NAME": {
            "content": "Class::C3 - A pragma to use the C3 method resolution order algorithm\n",
            "subsections": []
        },
        "SYNOPSIS": {
            "content": "# NOTE - DO NOT USE Class::C3 directly as a user, use MRO::Compat instead!\npackage ClassA;\nuse Class::C3;\nsub hello { 'A::hello' }\n\npackage ClassB;\nuse base 'ClassA';\nuse Class::C3;\n\npackage ClassC;\nuse base 'ClassA';\nuse Class::C3;\n\nsub hello { 'C::hello' }\n\npackage ClassD;\nuse base ('ClassB', 'ClassC');\nuse Class::C3;\n\n# Classic Diamond MI pattern\n#    <A>\n#   /   \\\n# <B>   <C>\n#   \\   /\n#    <D>\n\npackage main;\n\n# initializez the C3 module\n# (formerly called in INIT)\nClass::C3::initialize();\n\nprint join ', ' => Class::C3::calculateMRO('ClassD'); # prints ClassD, ClassB, ClassC, ClassA\n\nprint ClassD->hello(); # prints 'C::hello' instead of the standard p5 'A::hello'\n\nClassD->can('hello')->();          # can() also works correctly\nUNIVERSAL::can('ClassD', 'hello'); # as does UNIVERSAL::can()\n",
            "subsections": []
        },
        "DESCRIPTION": {
            "content": "This is pragma to change Perl 5's standard method resolution order from depth-first\nleft-to-right (a.k.a - pre-order) to the more sophisticated C3 method resolution order.\n\nNOTE: YOU SHOULD NOT USE THIS MODULE DIRECTLY - The feature provided is integrated into perl\nversion >= 5.9.5, and you should use MRO::Compat instead, which will use the core implementation\nin newer perls, but fallback to using this implementation on older perls.\n\nWhat is C3?\nC3 is the name of an algorithm which aims to provide a sane method resolution order under\nmultiple inheritance. It was first introduced in the language Dylan (see links in the \"SEE ALSO\"\nsection), and then later adopted as the preferred MRO (Method Resolution Order) for the\nnew-style classes in Python 2.3. Most recently it has been adopted as the 'canonical' MRO for\nPerl 6 classes, and the default MRO for Parrot objects as well.\n",
            "subsections": [
                {
                    "name": "How does C3 work.",
                    "content": "C3 works by always preserving local precedence ordering. This essentially means that no class\nwill appear before any of its subclasses. Take the classic diamond inheritance pattern for\ninstance:\n\n<A>\n/   \\\n<B>   <C>\n\\   /\n<D>\n\nThe standard Perl 5 MRO would be (D, B, A, C). The result being that A appears before C, even\nthough C is the subclass of A. The C3 MRO algorithm however, produces the following MRO (D, B,\nC, A), which does not have this same issue.\n\nThis example is fairly trivial, for more complex examples and a deeper explanation, see the\nlinks in the \"SEE ALSO\" section.\n\nHow does this module work?\nThis module uses a technique similar to Perl 5's method caching. When \"Class::C3::initialize\" is\ncalled, this module calculates the MRO of all the classes which called \"use Class::C3\". It then\ngathers information from the symbol tables of each of those classes, and builds a set of method\naliases for the correct dispatch ordering. Once all these C3-based method tables are created, it\nthen adds the method aliases into the local classes symbol table.\n\nThe end result is actually classes with pre-cached method dispatch. However, this caching does\nnot do well if you start changing your @ISA or messing with class symbol tables, so you should\nconsider your classes to be effectively closed. See the CAVEATS section for more details.\n"
                }
            ]
        },
        "OPTIONAL LOWERCASE PRAGMA": {
            "content": "This release also includes an optional module c3 in the opt/ folder. I did not include this in\nthe regular install since lowercase module names are considered *\"bad\"* by some people. However\nI think that code looks much nicer like this:\n\npackage MyClass;\nuse c3;\n\nThis is more clunky:\n\npackage MyClass;\nuse Class::C3;\n\nBut hey, it's your choice, that's why it is optional.\n",
            "subsections": []
        },
        "FUNCTIONS": {
            "content": "calculateMRO ($class)\nGiven a $class this will return an array of class names in the proper C3 method resolution\norder.\n\ninitialize\nThis must be called to initialize the C3 method dispatch tables, this module will not work\nif you do not do this. It is advised to do this as soon as possible after loading any\nclasses which use C3. Here is a quick code example:\n\npackage Foo;\nuse Class::C3;\n# ... Foo methods here\n\npackage Bar;\nuse Class::C3;\nuse base 'Foo';\n# ... Bar methods here\n\npackage main;\n\nClass::C3::initialize(); # now it is safe to use Foo and Bar\n\nThis function used to be called automatically for you in the INIT phase of the perl\ncompiler, but that lead to warnings if this module was required at runtime. After discussion\nwith my user base (the DBIx::Class folks), we decided that calling this in INIT was more of\nan annoyance than a convenience. I apologize to anyone this causes problems for (although I\nwould be very surprised if I had any other users other than the DBIx::Class folks). The\nsimplest solution of course is to define your own INIT method which calls this function.\n\nNOTE:\n\nIf \"initialize\" detects that \"initialize\" has already been executed, it will \"uninitialize\"\nand clear the MRO cache first.\n\nuninitialize\nCalling this function results in the removal of all cached methods, and the restoration of\nthe old Perl 5 style dispatch order (depth-first, left-to-right).\n\nreinitialize\nThis is an alias for \"initialize\" above.\n",
            "subsections": []
        },
        "METHOD REDISPATCHING": {
            "content": "It is always useful to be able to re-dispatch your method call to the \"next most applicable\nmethod\". This module provides a pseudo package along the lines of \"SUPER::\" or \"NEXT::\" which\nwill re-dispatch the method along the C3 linearization. This is best shown with an example.\n\n# a classic diamond MI pattern ...\n#    <A>\n#   /   \\\n# <B>   <C>\n#   \\   /\n#    <D>\n\npackage ClassA;\nuse Class::C3;\nsub foo { 'ClassA::foo' }\n\npackage ClassB;\nuse base 'ClassA';\nuse Class::C3;\nsub foo { 'ClassB::foo => ' . (shift)->next::method() }\n\npackage ClassC;\nuse base 'ClassA';\nuse Class::C3;\nsub foo { 'ClassC::foo => ' . (shift)->next::method() }\n\npackage ClassD;\nuse base ('ClassB', 'ClassC');\nuse Class::C3;\nsub foo { 'ClassD::foo => ' . (shift)->next::method() }\n\nprint ClassD->foo; # prints out \"ClassD::foo => ClassB::foo => ClassC::foo => ClassA::foo\"\n\nA few things to note. First, we do not require you to add on the method name to the\n\"next::method\" call (this is unlike \"NEXT::\" and \"SUPER::\" which do require that). This helps to\nenforce the rule that you cannot dispatch to a method of a different name (this is how \"NEXT::\"\nbehaves as well).\n\nThe next thing to keep in mind is that you will need to pass all arguments to \"next::method\". It\ncan not automatically use the current @.\n\nIf \"next::method\" cannot find a next method to re-dispatch the call to, it will throw an\nexception. You can use \"next::can\" to see if \"next::method\" will succeed before you call it like\nso:\n\n$self->next::method(@) if $self->next::can;\n\nAdditionally, you can use \"maybe::next::method\" as a shortcut to only call the next method if it\nexists. The previous example could be simply written as:\n\n$self->maybe::next::method(@);\n\nThere are some caveats about using \"next::method\", see below for those.\n",
            "subsections": []
        },
        "CAVEATS": {
            "content": "This module used to be labeled as *experimental*, however it has now been pretty heavily tested\nby the good folks over at DBIx::Class and I am confident this module is perfectly usable for\nwhatever your needs might be.\n\nBut there are still caveats, so here goes ...\n\nUse of \"SUPER::\".\nThe idea of \"SUPER::\" under multiple inheritance is ambiguous, and generally not recommended\nanyway. However, its use in conjunction with this module is very much not recommended, and\nin fact very discouraged. The recommended approach is to instead use the supplied\n\"next::method\" feature, see more details on its usage above.\n\nChanging @ISA.\nIt is the author's opinion that changing @ISA at runtime is pure insanity anyway. However,\npeople do it, so I must caveat. Any changes to the @ISA will not be reflected in the MRO\ncalculated by this module, and therefore probably won't even show up. If you do this, you\nwill need to call \"reinitialize\" in order to recalculate all method dispatch tables. See the\n\"reinitialize\" documentation and an example in t/20reinitialize.t for more information.\n\nAdding/deleting methods from class symbol tables.\nThis module calculates the MRO for each requested class by interrogating the symbol tables\nof said classes. So any symbol table manipulation which takes place after our INIT phase is\nrun will not be reflected in the calculated MRO. Just as with changing the @ISA, you will\nneed to call \"reinitialize\" for any changes you make to take effect.\n\nCalling \"next::method\" from methods defined outside the class\nThere is an edge case when using \"next::method\" from within a subroutine which was created\nin a different module than the one it is called from. It sounds complicated, but it really\nisn't. Here is an example which will not work correctly:\n\n*Foo::foo = sub { (shift)->next::method(@) };\n\nThe problem exists because the anonymous subroutine being assigned to the glob *Foo::foo\nwill show up in the call stack as being called \"ANON\" and not \"foo\" as you might expect.\nSince \"next::method\" uses \"caller\" to find the name of the method it was called in, it will\nfail in this case.\n\nBut fear not, there is a simple solution. The module \"Sub::Name\" will reach into the perl\ninternals and assign a name to an anonymous subroutine for you. Simply do this:\n\nuse Sub::Name 'subname';\n*Foo::foo = subname 'Foo::foo' => sub { (shift)->next::method(@) };\n\nand things will Just Work. Of course this is not always possible to do, but to be honest, I\njust can't manage to find a workaround for it, so until someone gives me a working patch\nthis will be a known limitation of this module.\n",
            "subsections": []
        },
        "COMPATIBILITY": {
            "content": "If your software requires Perl 5.9.5 or higher, you do not need Class::C3, you can simply \"use\nmro 'c3'\", and not worry about \"initialize()\", avoid some of the above caveats, and get the best\npossible performance. See mro for more details.\n\nIf your software is meant to work on earlier Perls, use Class::C3 as documented here. Class::C3\nwill detect Perl 5.9.5+ and take advantage of the core support when available.\n",
            "subsections": []
        },
        "Class::C3::XS": {
            "content": "This module will load Class::C3::XS if it's installed and you are running on a Perl version\nolder than 5.9.5. The optional module will be automatically installed for you if a C compiler is\navailable, as it results in significant performance improvements (but unlike the 5.9.5+ core\nsupport, it still has all of the same caveats as Class::C3).\n",
            "subsections": []
        },
        "CODE COVERAGE": {
            "content": "Devel::Cover was reporting 94.4% overall test coverage earlier in this module's life. Currently,\nthe test suite does things that break under coverage testing, but it is fair to assume the\ncoverage is still close to that value.\n",
            "subsections": []
        },
        "SEE ALSO": {
            "content": "",
            "subsections": [
                {
                    "name": "The original Dylan paper",
                    "content": "<https://web.archive.org/web/20000817033012id/http://www.webcom.com/haahr/dylan/linearization-o\nopsla96.html>\n"
                },
                {
                    "name": "The prototype Perl 6 Object Model uses C3",
                    "content": "<http://svn.openfoundry.org/pugs/perl5/Perl6-MetaModel/>\n"
                },
                {
                    "name": "Parrot now uses C3",
                    "content": "<http://aspn.activestate.com/ASPN/Mail/Message/perl6-internals/2746631>\n<http://use.perl.org/~autrijus/journal/25768>\n"
                },
                {
                    "name": "Python 2.3 MRO related links",
                    "content": "<http://www.python.org/2.3/mro.html>\n<http://www.python.org/2.2.2/descrintro.html#mro>\n\nC3 for TinyCLOS\n<http://www.call-with-current-continuation.org/eggs/c3.html>\n"
                }
            ]
        },
        "ACKNOWLEGEMENTS": {
            "content": "Thanks to Matt S. Trout for using this module in his module DBIx::Class and finding many bugs\nand providing fixes.\nThanks to Justin Guenther for making \"next::method\" more robust by handling calls inside \"eval\"\nand anon-subs.\nThanks to Robert Norris for adding support for \"next::can\" and \"maybe::next::method\".\n",
            "subsections": []
        },
        "AUTHOR": {
            "content": "Stevan Little, <stevan@iinteractive.com>\n\nBrandon L. Black, <blblack@gmail.com>\n",
            "subsections": []
        },
        "COPYRIGHT AND LICENSE": {
            "content": "Copyright 2005, 2006 by Infinity Interactive, Inc.\n\n<http://www.iinteractive.com>\n\nThis library is free software; you can redistribute it and/or modify it under the same terms as\nPerl itself.\n",
            "subsections": []
        }
    },
    "summary": "Class::C3 - A pragma to use the C3 method resolution order algorithm",
    "flags": [],
    "examples": [],
    "see_also": []
}