{"id":22351053,"url":"https://github.com/johnae/classy","last_synced_at":"2026-03-19T22:31:33.564Z","repository":{"id":136753434,"uuid":"66073212","full_name":"johnae/classy","owner":"johnae","description":"Classy is a class implementation for MoonScript and Lua","archived":false,"fork":false,"pushed_at":"2017-07-07T13:55:59.000Z","size":26,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-13T13:08:38.163Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"MoonScript","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/johnae.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-08-19T10:04:53.000Z","updated_at":"2023-03-17T20:50:48.000Z","dependencies_parsed_at":null,"dependency_job_id":"139fcfa9-ce0e-4087-8167-a30015c02335","html_url":"https://github.com/johnae/classy","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/johnae/classy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnae%2Fclassy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnae%2Fclassy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnae%2Fclassy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnae%2Fclassy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johnae","download_url":"https://codeload.github.com/johnae/classy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johnae%2Fclassy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28941921,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-31T11:39:38.044Z","status":"ssl_error","status_checked_at":"2026-01-31T11:39:27.765Z","response_time":128,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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-12-04T12:12:28.849Z","updated_at":"2026-01-31T12:01:59.746Z","avatar_url":"https://github.com/johnae.png","language":"MoonScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![CircleCI](https://circleci.com/gh/johnae/classy.svg?style=svg)](https://circleci.com/gh/johnae/classy)\n\n# Classy\n\nhttps://github.com/johnae/classy\n\n## Description\nClassy is a class implementation for [MoonScript](https://github.com/leafo/moonscript) (and [Lua](http://www.lua.org)). It is mainly for MoonScript however since that allows a certain syntax which looks pretty good i.m.o. I haven't used it from Lua but I expect the syntax to become more verbose and definitely uglier.\n\n## Lua compatibility\n\nI know this works with LuaJIT 2.x+. It should work with other Lua implementations too - but I haven't tried. The CircleCI tests run on LuaJIT. Please test and help out if you feel like it.\n\n## Performance\n\nI haven't done any extensive performance tests but it seems to be slightly faster than MoonScript's built-in class implementation. Haven't compared to other implementations of which there are many.\n\n## Why\n\nBecause MoonScript's built-in class implementation makes it difficult to use metamethods. It's also a bit verbose in it's compiled lua output. And, of course, because it's fun.\n\n## Usage\n\nSee [spec/classy_spec.moon](spec/classy_spec.moon) and [spec/smoke_test_spec.moon](spec/smoke_test_spec.moon) for more examples.\n\n```moonscript\ndefine = require'classy'.define -- call the local whatever you like, I like 'define'\nformat = string.format\n\nDate = define 'Date', -\u003e\n\n  properties\n\n    age:\n      get: =\u003e\n        now = os.date('*t')\n        age = now.year - @year\n        if now.month \u003c @month\n          age = age - 1\n        else if now.month == @month\n          if now.day \u003c @day\n            age = age - 1\n        age\n      set: (age) =\u003e\n        today = os.date('*t')\n        @year = today.year - age\n\n  static\n\n    from_string: (str) =\u003e\n      y, m, d = str\\match('(%d+)-(%d+)-(%d+)')\n      y, m, d = tonumber(y), tonumber(m), tonumber(d)\n      new y, m, d\n\n  instance\n\n    initialize: (year, month, day) =\u003e\n      @year, @month, @day = tonumber(year), tonumber(month), tonumber(day)\n\n  meta\n\n    __tostring: =\u003e\n      y, m, d = @year, format('%02d', @month), format('%02d', @day)\n      \"#{y}-#{m}-#{d}\"\n\n    __add: (num_days) =\u003e\n      s = num_days*24*60*60\n      d = os.time year: @year, month: @month, day: @day\n      newdate = os.date '*t', d+s\n      new newdate.year, newdate.month, newdate.day\n\n    __sub: (num_days) =\u003e\n      s = num_days*24*60*60\n      d = os.time year: @year, month: @month, day: @day\n      newdate = os.date '*t', d-s\n      new newdate.year, newdate.month, newdate.day\n\nPerson = define 'Person', -\u003e\n\n  accessors\n\n    attributes: {'firstname', 'lastname'}\n\n  properties\n\n    name: =\u003e \"#{@firstname} #{@lastname}\"\n    birthdate:\n      get: =\u003e tostring(@attributes.birthdate)\n      set: (date) =\u003e @attributes.birthdate = Date\\from_string(date)\n    age:\n      get: =\u003e @attributes.birthdate.age\n      set: (age) =\u003e @attributes.birthdate.age = age\n\n  static\n\n    find: (name) =\u003e\n      name = name\\lower!\n      @some_people or= {\n        new('Bob', 'Johnsson', '1964-03-02'),\n        new('Mary', 'Jensen', '1983-05-10'),\n        new('Victoria', 'Hammadi', '1989-12-15')\n      }\n      [p for p in *@some_people when p.name\\lower!\\match name]\n\n  instance\n\n    initialize: (firstname, lastname, birthdate) =\u003e\n      @attributes = {:firstname, :lastname, birthdate: Date\\from_string(birthdate)}\n\n-- subclass of Person\nEmployee = define 'Employee', -\u003e\n  parent Person\n\n  static\n\n    from_person: (p, salary) =\u003e\n      {:firstname, :lastname, :birthdate} = p.attributes\n      birthdate = tostring(birthdate)\n      new :firstname, :lastname, :birthdate, :salary\n\n  instance\n\n    initialize: (opts={}) =\u003e\n      {:firstname, :lastname, :birthdate} = opts\n      super @, firstname, lastname, birthdate\n      @salary = opts.salary\n\nd = Date.new 1978, 1, 5\nprint tostring(d) -- prints '1978-01-05'\nnew_year_1977 = d - 5\nprint tostring(new_year_1977) -- prints '1977-12-31'\n\np = Person.new 'John', 'Eriksson', '1978-01-05'\nprint p.firstname -- prints the firstname in the @attributes table\nprint p.age -- prints the calculated age\nprint p.birthdate -- print the birthdate\np.age = 37 -- changes the birthdate\nprint p.age -- prints 37\nprint p.birthdate -- prints the new birthdate\nprint p.name -- prints the name by concatenating firstname and lastname\n\nbob = Person\\find('john')[1] -- static method, finds Bob (his lastname is Johnsson)\nprint bob.name -- prints \"Bob Johnsson\"\nprint bob.age -- prints the calculated age\n\nemployee = Employee\\from_person bob, 1000000\nprint employee.name -- prints \"Bob Johnsson\"\nprint employee.age -- prints calculated age\nprint employee.salary -- prints 1000000\n\n-- some_table == some_table is true in lua, some_table == some_other_table is false in lua\nprint employee == employee -- prints true\n\ncloned_employee = employee\\dup!\nprint cloned_employee.name -- prints \"Bob Johnsson\"\nprint cloned_employee.age -- prints calculated age\nprint cloned_employee.salary -- prints 1000000\nprint cloned_employee == employee -- prints false\ncloned_employee.salary = 100\nprint cloned_employee.salary -- prints 100\nprint employee.salary -- prints 1000000\n```\n\nAbove demonstrates some of what this library can do. There is more, like missing_property for example. See [spec/classy_spec.moon](spec/classy_spec.moon).\n\n## Development\n\nRunning the tests requires busted https://github.com/Olivine-Labs/busted and luassert https://github.com/Olivine-Labs/luassert.\nSince luassert comes with busted, only busted needs to be installed really. It also requires that moonscript is installed.\n\nOn Ubuntu you might go about it like this:\n\n```shell\nsudo apt-get install luarocks luajit\nsudo luarocks install busted\nsudo luarocks install moonscript\n```\n\nTo run the specs, run `busted spec`.\n\n\n## Contributing\n\nI appreciate all feedback and help. If there's a problem, create an issue or pull request. Thanks!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnae%2Fclassy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohnae%2Fclassy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohnae%2Fclassy/lists"}