Skip to content

OOP

The OOP library implements a OOP system that supports multiple inheritance.

A class is defined by a class definition table, passed onto RegisterClass() to initialize and register it. Classes to inherit from are defined during this call and cannot be changed afterwards. Instances of the classes will inherit keys from their class definition table.

Inheritance is done via metatables, however special logic is used to extend this functionality to allow for multiple inheritance.

If class A inherits from class B and C, indexing an instance (or the definition) of class A will:

  1. Check for the presence of the key within the instance/definition of A
  2. Check for the presence of the key within each superclass, in order of inheritance established during RegisterClass() (from first to last). This is done recursively for any superclasses those classes might have.
  3. Invoke __index of the class.

There is currently no support for multiple inheritance of metamethods. They will only be checked in the direct superclass.

There is no public constructor for classes by design; it is up to you to explicitly declare one. In Epip, these are typically called Create(). __call is not used for clarity reasons, as well as limitations in how it can be annotated (ex. no comments for parameters).

Constructors must call ClassDefinition:__Create() to create an instance. This method takes an optional table parameter; if present, that table will become the class instance, keeping any keys it had already set. This is typically also the parameter of the public constructor, so as to avoid bloating the constructor's formal parameters, instead providing them via a table. Within your constructor you may afterwards perform any initializations of your own as necessary.

As mentioned before, an instance must be of a single class type, and there are no public constructors; as a result, it is not possible to make an "anonymous" class that inherits from multiple classes. You must register an explicit class that inherits from the classes you want.

Class instances are of the Class type. This type provides several utility methods for type-checking.

When annotating your classes, be sure to make them inherit from Class to denote they use the OOP system as well as to expose the utility methods in the IDE.

Note that Feature has integration with this library that allows registering and fetching classes related to the feature itself. If working with features, their calls should be used instead, as they will likely get automatic namespacing in the future. Currently, class names must be unique, lest new registrations will overwrite the previous definition.

OOPLib Class

Methods

GetClass
function OOPLib.GetClass(className)
   -> `T`

Returns the base table for a class.

Throws if the class is not registered.

@param className `T`

ImplementsClass
function OOPLib.ImplementsClass(tbl, class)

Returns whether a table implements a class.

@param tbl table|Class

@param class string|Class

IsClass
function OOPLib.IsClass(tbl, class)
   -> boolean

Returns whether a table is a class table or instance.

@param tbl table|Class

@param class (string|Class)? If present, `true` will only be returned if the table *is* the exact requested class.

RegisterClass
function OOPLib.RegisterClass(className, class, parentClasses)
   -> `T`

Registers a class.

@param className string|`T`

@param class table

@param parentClasses string[]? Classes this one inherits from.

SetMetatable
function OOPLib.SetMetatable(table, metatable)

Sets a table's metatable. __index is set to index the metatable itself, using the metatable's __index as a fallback.

@param table table Mutated.

@param metatable table

Class Class

Methods

GetClassDefinition
function Class:GetClassDefinition()
   -> Class

Returns the main table that defines this class instance.

GetClassName
function Class:GetClassName()
   -> string

Returns the name of the class.

GetParentClasses
function Class:GetParentClasses()
   -> Class[]

Returns the parent classes of the class.

ImplementsClass
function Class:ImplementsClass(class)
   -> boolean

Returns whether this class implements another.

Hierarchies are considered.

Will return true if this class is the queried one.

@param class string|Class

__Create
---@protected
function Class:__Create(data)
   -> Class

Creates a new instance of the class.

@param data table? Table with the initial fields of the instance.

__Error
---@protected
function Class:__Error(..., method)

Throws an error prefixed with the class and method name, blaming the third-level function in the stack - usually user code.

@param ... any

@param method string

__GetLoggingPrefix
---@protected
function Class:__GetLoggingPrefix()
   -> string

Returns the prefix to use for logging messages.

__InternalError
---@protected
function Class:__InternalError(method, ...)

Throws an error prefixed with the class and method name caused at the callee function.

@param method string

@param ... any

__Log
---@protected
function Class:__Log(...)

Logs a message.

@param ... any

__LogError
---@protected
function Class:__LogError(...)

Logs an error without halting execution.

@param ... any

__LogNotImplemented
---@protected
function Class:__LogNotImplemented(methodName)

Logs a "Not implemented" warning. Use as a placeholder.

@param methodName string

__LogWarning
---@protected
function Class:__LogWarning(...)

Logs a warning.

Requires logging level to be set to WARN or lower.

@param ... any

__ThrowNotImplemented
---@protected
function Class:__ThrowNotImplemented(methodName)

Throws a "Not implemented" error. Use as a placeholder.

@param methodName string