{"id":13895997,"url":"https://github.com/lua-rocks/proto","last_synced_at":"2025-07-17T11:32:48.254Z","repository":{"id":218915779,"uuid":"423398293","full_name":"lua-rocks/proto","owner":"lua-rocks","description":"OOP library","archived":false,"fork":false,"pushed_at":"2022-01-27T14:06:40.000Z","size":116,"stargazers_count":8,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-08-07T18:37:32.559Z","etag":null,"topics":["lua","oop"],"latest_commit_sha":null,"homepage":"","language":"Lua","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/lua-rocks.png","metadata":{"files":{"readme":"readme.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"license.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2021-11-01T08:57:31.000Z","updated_at":"2023-08-20T21:21:29.000Z","dependencies_parsed_at":"2024-01-24T14:11:45.399Z","dependency_job_id":null,"html_url":"https://github.com/lua-rocks/proto","commit_stats":null,"previous_names":["lua-rocks/proto"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lua-rocks%2Fproto","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lua-rocks%2Fproto/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lua-rocks%2Fproto/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lua-rocks%2Fproto/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lua-rocks","download_url":"https://codeload.github.com/lua-rocks/proto/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":226260601,"owners_count":17596494,"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":["lua","oop"],"created_at":"2024-08-06T18:02:36.182Z","updated_at":"2024-11-25T01:30:53.525Z","avatar_url":"https://github.com/lua-rocks.png","language":"Lua","readme":"# `PRÖTØ` - the simplest prototype ÖØP in Lua\n\n## 🎉 GOOD NEWS EVERYONE 🎉\n\nSEE [CHANGELOG](changelog.md).\n\n## Why?\n\nIt's no secret that there is a huge variety of different OOP libraries for Lua\nand I'm even the author of one of them, but why did I think about writing one\nmore?\n\nThe fact is that no matter how lite and simple library is, it may somehow have\nits own rules that the object-table must follow, and most often such tables are\nmodified (infected) with libraries, receiving various methods from them, without\nwhich the table can not be considered object at all.\n\nSo I decided to write a library that treats absolutely any table as object. It\ndoes not matter where this table came from, how it was created or what is inside\nit. In fact, this library is just a set of auxiliary functions for working with\nany tables in OOP style.\n\n## Installation\n\n`luarocks install proto`\n\nOr download/clone the lua file/repository into your project, To have smart tips\nin [VSCodium][2].\n\n## General principles and terminology\n\nNote that PRÖTØ uses a programming paradigm called [prototype programming][1].\nThe main difference between prototype-based and class-based OOP is that we have\nno concept of Class.\n\nIt's very simple: instead of creating classes and their instances, we create an\nordinary table and specify its \"relatives\" using this library, which it will\nrefer to via the `__index` meta-method. In this case we call all tables as\ntables instead of objects or classes, which in theory makes our life easier and\nmore pleasant 😺.\n\nJust as a table in lua combines an object and an array, we can also use the\ngeneric term \"slot\" when talking about methods or fields, as long as we don't\nfocus on the type of variable.\n\nFor example: the `__index` metamethod is more correctly called **metaslot**,\nbecause it can be both a function and a table.\n\nOur tables have no library garbage, so they don't even have constructor\nfunctions, but you can create your own:\n\n```lua\nlocal proto = require \"proto\"\n\nlocal o = {}\n\nfunction o:init(conf)\n  -- This way we can init inherited objects:\n  proto.get_index(self).init(self, conf)\n\n  self.conf = conf\n  return self\nend\n\n-- For one instance we can simply init our table and start using it.\no:init(conf)\n\n-- For many instances we need to use library.\nlocal another_o = proto.link({}, o):init(conf)\n```\n\nThere is one thing you should know, which can make your life much easier - you\nno need to use interface (table `conf` in example above) as constructor argument\n(`init(conf)`)! You can just use it as first argument in `proto.link`, so you\nwill no need to write annoying code like `self.something = conf.something`. And\nalso you will no need to describe interfaces. Object can be interface to itself.\n\nExample:\n\n```lua\nfunction Vector:init()\n  --- Deprecated:\n  -- self[1] = conf[1]\n  -- self[2] = conf[2]\n  -- self[...] = conf[...]\n\n  -- Initializing proto-object this way is also easier, because we don't need\n  -- to check how many arguments it accepts. The argument is always one: self.\n  proto.get_index(self).init(self)\n\n  -- `self` is already `conf`!\n  -- You only have to correct it (if needed):\n  if type(self[1]) == \"string\" then self[1] == tonumber(self[1]) end\n\n  return self\nend\n\nlocal v = proto.link({\"640\", 480}, Vector):init()\n```\n\nIn this case you can use `proto.new`, which will automatically call table's\n`init` method right after linking (with one argument: self).\n\n```lua\nlocal v = proto.new(Vector, {\"640\", 480})\n```\n\nI advise you to capitalize variables **only** when they are used as prototypes,\nlike `Vector` in examples above.\n\n## Arsenal\n\nWe have only 7 simple but powerful tools at our disposal:\n\n- Main:\n  - `proto.link(t1, t2, name?)`: inheritance (linking tables via `__index`)\n  - `proto.copy(t)`: sometimes cloning copies is faster than building\n- Iterators:\n  - `proto.parents(t, limit?)`: for all linked tables\n  - `proto.slots(t, limit?)`: for all slots from `t` and linked tables\n- Helpers:\n  - `proto.get_index(t)`: get `__index` metaslot\n  - `proto.set_name(t, name?)`: set `__tostring` metaslot\n  - `proto.new(super, init, name?)`: constructor for tables with `init` method\n\nFor detailed API see [init.lua](init.lua), examples in\n[example.lua](example.lua).\n\n## Recommended extensions for VSCodium\n\n- `sumneko.lua` - smart tips on all my functions and more\n- `rog2.luacheck` - linter\n- `tomblind.local-lua-debugger-vscode` - debugger\n\n## Caveats\n\nThis library is still very young and poorly covered by tests, so it can easily\nhave bugs, inaccuracies and defects, but at the same time it is pretty simple\nand fix any bug is not very difficult. So if you find a bug or if you have any\nidea how to improve it - feel free to create issues!\n\n[1]: https://en.wikipedia.org/wiki/Prototype-based_programming\n[2]: https://vscodium.com\n","funding_links":[],"categories":["Lua"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flua-rocks%2Fproto","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flua-rocks%2Fproto","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flua-rocks%2Fproto/lists"}