{"id":20634145,"url":"https://github.com/samn/croup","last_synced_at":"2026-04-20T12:03:48.577Z","repository":{"id":1317273,"uuid":"1262148","full_name":"samn/Croup","owner":"samn","description":"Class Grouping and composition in javascript","archived":false,"fork":false,"pushed_at":"2011-02-07T18:25:26.000Z","size":120,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-17T07:40:36.432Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-01-17T02:49:28.000Z","updated_at":"2013-10-20T19:38:03.000Z","dependencies_parsed_at":"2022-08-16T13:05:13.463Z","dependency_job_id":null,"html_url":"https://github.com/samn/Croup","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samn%2FCroup","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samn%2FCroup/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samn%2FCroup/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samn%2FCroup/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samn","download_url":"https://codeload.github.com/samn/Croup/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242635331,"owners_count":20161437,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-16T14:23:58.312Z","updated_at":"2026-04-20T12:03:48.533Z","avatar_url":"https://github.com/samn.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"#Croup\n*Class composition by Grouping in JavaScript*\n\n##Motivation\nSharing code between classes is good but doing it with inheritance can introduce\nunwanted semantic side effects.  Inheritance models an `is-a` relationship which\nis sometimes appropriate but problems can occur when classes are refactored,\nchanging the taxonomy.  \n\n\nCroup aims to provide the code reuse benefits of inheritance without the\nsemantic implications.  Rather than defining a relationship between code through\nancestry, code that is shared among classes is grouped together in a flat\ntaxonomy.  Classes that have common code are 'Crouped' together.\n\nFor Example:\n\n    Croup.these('ClassA', 'ClassB').have({\n        aMethod: function(arg1, arg2) {\n            // do something\n        }\n    });\n\n    a = new ClassA();\n    typeof a.aMethod // method\n\n    b = new ClassB();\n    typeof b.aMethod // method\n\n##Multiple Definitions\nCroup automatically defines ClassA and ClassB, which both have a method called\naMethod. Classes can also be defined in multiple places and are constructed as a\ncomposition of their definitions.  This allows code to be shared between\nmultiple classes without an additional semantic relation.\n\n\n    // Methods common to ClassA \u0026 ClassB\n    Croup.these('ClassA', 'ClassB').have({\n        methodA: function() {\n            // ...\n        },\n        methodB: function() {\n            // ...\n        }\n    });\n\n    // Methods common to ClassA \u0026 ClassC\n    Croup.these('ClassA', 'ClassC').have({\n        methodC: function() {\n            // ...\n        }\n    });\n\n    ca = new ClassA();\n    typeof ca.methodA // method\n    typeof ca.methodB // method\n    typeof ca.methodC // method\n\n    cb = new ClassB();\n    typeof cb.methodA // method\n    typeof cb.methodB // method\n    typeof cb.methodC // undefined\n\n    cc = new ClassC();\n    typeof cc.methodA // undefined\n    typeof cc.methodB // undefined\n    typeof cc.methodC // method\n\nIf you want to override the definition of a method you can redefine it like you\nnormally would:\n\n    ClassA.prototype.methodA = function() { ... };\n\n\n##Constructors\nConstructors can be defined as well.  If multiple constructors are included in a\nclass's definitions they will all execute.  Arguments can be passed to a\nconstructor using a dictionary.\n\n    \n    Croup.these('ClassA', 'ClassB').have({\n        constructor: function(args) {\n            this.property = args['message1'];\n            alert(this.property);\n        }\n    });\n\n    Croup.these('ClassA', 'ClassC').have({\n        constructor: function(args) {\n            alert(args['message2']);\n        }\n    });\n\n    ca = new ClassA({message1: 'Hello', message2: 'World!'});\n    // alerts 'Hello' then 'World!'\n\n##Namespaces\nBy Default Croup injects classes into the global namespace, but if you'd like to\ndefine a class in a different scope you can pass a reference to that scope to\nthe `have` method:\n\n    function Foo() {\n        Croup.these('Bar').have({\n            method1: function() {\n                // ...\n            }\n        }, Foo);\n        bar = new Foo.Bar();\n        bar.method1();\n    }\n    \n    typeof Bar // undefined\n\n##Drawbacks\n* No polymorphism since there is no relationship between classes\n    * though JavaScript doesn't dispatch on argument types\n* The name is really dumb `(CROUP -\u003e Class gROUP ??)`\n\n##Feedback\nThis is an experiment, not sure if it's useful or not, but I'd love to hear any feedback:\nsamneubardt+croup@gmail.com\n[@gnubardt](http://twitter.com/gnubardt)\n\n**LICENSE**\nCroup is Copyright (c) 2011 Sam Neubardt and distributed under the MIT license.\nSee the `LICENSE` file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamn%2Fcroup","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamn%2Fcroup","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamn%2Fcroup/lists"}