### Define and Use Classes in Lua with LibTSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/Docs/index.md Demonstrates defining a base class, a subclass, and instantiating objects with methods for initialization, getting, setting, and adding values. Requires LibStub to be available. ```lua local LibTSMClass = LibStub("LibTSMClass") local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass:__init(value) self._value = value end function MyClass:GetValue() return self._value end function MyClass:SetValue(value) self._value = value end local MySubClass = LibTSMClass.DefineClass("MySubClass", MyClass) function MySubClass:AddValue(value) self:SetValue(self:GetValue() + value) end local obj = MySubClass(4) print(obj:GetValue()) -- 4 obj:SetValue(10) print(obj:GetValue()) -- 10 obj:AddValue(5) print(obj:GetValue()) -- 15 ``` -------------------------------- ### Instance Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/MANIFEST.md Provides a complete reference for 8 core instance methods, including special fields like `__class` and `__super`, constructor `__init`, string representation, equality comparison, debugging, type checking, casting, and closure handling. Details access control and includes multiple examples per method. ```APIDOC ## Instance Methods Reference ### Description Complete reference for 8 instance methods, covering special fields, constructor, string representation, equality comparison, debugging, type checking, casting, and closures. Details access control and includes multiple examples per method. ### Methods - **__class**: Access the class of the instance. - **__super**: Access the superclass of the instance. - **__init**: Constructor behavior. - **__tostring**: String representation of the instance. - **ToDebugString**: Debug string representation. - **__equals**: Equality comparison between instances. - **__dump**: Debugging information for the instance. - **__isa**: Type checking for the instance. - **__as**: Casting the instance to a specific type. - **__closure**: Handling of closures associated with the instance. ### Access Control - Details access control mechanisms for instance members. ### Examples - Multiple examples provided for each method. ``` -------------------------------- ### Virtual Method Example in Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Virtual-Methods.md This example defines a base class 'Animal' with a virtual method 'GetSpecies' and a method 'Describe' that calls 'GetSpecies'. It then defines a derived class 'Dog' that overrides 'GetSpecies'. The output shows how 'Describe' correctly calls the overridden 'GetSpecies' based on the instance type. ```lua local Animal = LibTSMClass.DefineClass("Animal") function Animal:GetSpecies() return "Generic Animal" end function Animal:Describe() -- This calls GetSpecies, but which GetSpecies? return "I am a " .. self:GetSpecies() end local Dog = LibTSMClass.DefineClass("Dog", Animal) function Dog:GetSpecies() return "Dog" end local animal = Animal() print(animal:Describe()) -- prints "I am a Generic Animal" local dog = Dog() print(dog:Describe()) -- prints "I am a Dog" ``` -------------------------------- ### Basic Debug Output Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/GetDebugInfo.md Demonstrates how to get a basic debug string for a class instance. Ensure the instance is created and its string representation is used as the first argument. The second argument controls the inspection depth. ```lua local LibTSMClass = LibStub("LibTSMClass") local Person = LibTSMClass.DefineClass("Person") function Person:__init(name, age) self.name = name self.age = age self.metadata = { created = "2025-06-23", version = 1 } end local person = Person("Alice", 30) print(person) -- prints "Person:00ABC123" (example address) -- Later, retrieve debug info by string representation local debugInfo = LibTSMClass.GetDebugInfo("Person:00ABC123", 2) if debugInfo then print(debugInfo) -- Outputs: -- self = { -- name = "Alice" -- age = 30 -- metadata = { -- created = "2025-06-23" -- version = 1 -- } -- } end ``` -------------------------------- ### Overriding Method Using Inheritance Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/extensions.md This example shows the correct way to override an existing method by defining a subclass using inheritance in LibTSMClass. ```lua local Base = LibTSMClass.DefineClass("Base") function Base:ExistingMethod() return "original" end -- For overriding, create a subclass local Derived = LibTSMClass.DefineClass("Derived", Base) function Derived:ExistingMethod() return "override" end ``` -------------------------------- ### Virtual Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/MANIFEST.md Explains the mechanism of virtual methods, including runtime type-based resolution, the template method pattern, and handling multiple inheritance levels. Covers access control, performance implications, and provides over 10 comprehensive examples. ```APIDOC ## Virtual Methods ### Description Explains the mechanism of virtual methods, including runtime type-based resolution, the template method pattern, and handling multiple inheritance levels. Covers access control, performance implications, and provides over 10 comprehensive examples. ### How Virtual Methods Work - Runtime type-based resolution. - Template method pattern implementation. - Support for multiple inheritance levels. ### Access Control - Details access control rules applied to virtual methods. ### Performance - Discusses performance implications of using virtual methods. ### Examples - 10+ comprehensive examples demonstrating various use cases. ``` -------------------------------- ### Define Static Method with Access Control Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md Shows the definition of a static method that respects access control. This example highlights that static methods can be defined with modifiers, though extensions cannot have private or protected methods. ```lua local Service = LibTSMClass.DefineClass("Service") function Service.__static.GetStatus() return "online" end -- Static methods respect access control: -- This would work in the class but not via extensions ``` -------------------------------- ### Group Related Classes for Organization Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/best-practices.md Organize your classes logically by grouping related ones, for example, placing models in a 'models' directory and services in a 'services' directory. This improves code structure and discoverability. ```lua -- models/User.lua local User = LibTSMClass.DefineClass("User") -- models/Post.lua local Post = LibTSMClass.DefineClass("Post") -- services/UserService.lua local UserService = LibTSMClass.DefineClass("UserService") -- tests/TestUser.lua -- Test files paired with implementations ``` -------------------------------- ### Install LibTSMClass using BigWigs Packager Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/README.md Reference LibTSMClass as an external library in your BigWigs packager configuration. ```yaml externals: Libs/LibTSMClass: url: https://github.com/TradeSkillMaster/LibTSMClass.git ``` -------------------------------- ### Document Lua Constructors with Arguments and Throws Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/best-practices.md Document the constructor with its arguments, their types and requirements, and any potential errors it might throw. ```lua local User = LibTSMClass.DefineClass("User") -- Document the constructor --[[ __init(username: string, email: string) Creates a new User instance. Arguments: username - The user's login name (required) email - The user's email address (required) Throws: error if username or email is invalid ]] function User:__init(username, email) -- Implementation end ``` -------------------------------- ### Get Class Name - Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md Access the read-only __name field to retrieve the name of a class, useful for debugging and logging. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") print(MyClass.__name) -- prints "MyClass" ``` -------------------------------- ### Get Class Name with __name Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/Docs/features.md Access the `__name` attribute on a class to retrieve its string name. This is useful for introspection and debugging. ```lua print(MyClass.__name) -- prints "MyClass" ``` -------------------------------- ### Demonstrate Inheritance Chain and `__isa` Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/inheritance-and-polymorphism.md Illustrates how classes can inherit from classes that themselves inherit, and how to check the inheritance relationship using the `__isa` method. ```lua local Base = LibTSMClass.DefineClass("Base") local Middle = LibTSMClass.DefineClass("Middle", Base) local Derived = LibTSMClass.DefineClass("Derived", Middle) local inst = Derived() print(inst:__isa(Base)) -- prints true (indirect) print(inst:__isa(Middle)) -- prints true (direct parent) print(inst:__isa(Derived)) -- prints true (own class) ``` -------------------------------- ### Access Parent Class - Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md Use the __super field to get a reference to the parent class. It returns nil for base classes. ```lua local Base = LibTSMClass.DefineClass("Base") local Derived = LibTSMClass.DefineClass("Derived", Base) print(Derived.__super == Base) -- prints true print(Base.__super) -- prints nil ``` -------------------------------- ### Configuration Management with Defaults Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/static-members.md Manage application configuration using static members to store default and current settings, allowing overrides. ```lua local Config = LibTSMClass.DefineClass("Config") Config.defaults = { debug = false, logLevel = "info", maxRetries = 3 } Config.current = {} function Config.__static.Load(overrides) Config.current = {} for k, v in pairs(Config.defaults) do Config.current[k] = v end if overrides then for k, v in pairs(overrides) do Config.current[k] = v end end end function Config.__static.Get(key) return Config.current[key] end function Config.__static.Set(key, value) Config.current[key] = value end Config.Load({ debug = true }) print(Config.Get("debug")) -- prints true print(Config.Get("logLevel")) -- prints "info" ``` -------------------------------- ### Integrate LibTSMClass with LibStub Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/README.md Demonstrates how to include LibTSMClass as an external library in a BigWigs packager format and how to retrieve it using LibStub in addon code. ```lua -- In BigWigs packager format: externals: Libs/LibTSMClass: url: https://github.com/TradeSkillMaster/LibTSMClass.git -- In addon code: local LibTSMClass = LibStub("LibTSMClass") ``` -------------------------------- ### Accessing Instance Class Reference Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Instance-Methods.md Use the `__class` special field to get a reference to the class an instance belongs to. This is a read-only field set during instantiation. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") local inst = MyClass() print(inst.__class == MyClass) -- prints true print(inst.__class.__name) -- prints "MyClass" ``` -------------------------------- ### Instance Methods (Available on All Instances) Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/README.md Core methods available on all instances created by the class library. ```APIDOC ## Instance Methods ### `__init(...)` #### Description The constructor method for class instances. Called when an instance is created. ### `__tostring()` #### Description Returns a string representation of the instance. ### `__equals(other)` #### Description Compares the instance for equality with another object. ### `__dump()` #### Description Provides a pretty-printed representation of the instance's fields for debugging. ### `__isa(class)` #### Description Checks if the instance is of the specified class or a subclass. ### `__as(class)` #### Description Casts the instance to a parent class type, if applicable. ### `__closure(methodName)` #### Description Creates a callable closure for accessing restricted (private or protected) methods. ### `ToDebugString()` #### Description An alias for the `__tostring()` method, providing a string representation for debugging. ``` -------------------------------- ### Instance Constructor (`__init`) Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Instance-Methods.md The `__init` method is the constructor called automatically during class instantiation. It should not return any values and can accept variadic arguments. ```lua local Person = LibTSMClass.DefineClass("Person") function Person:__init(name, age) self.name = name self.age = age end local p = Person("Alice", 30) -- __init is called automatically ``` -------------------------------- ### Class Modification Restriction Example Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/README.md Demonstrates that once a class is subclassed, its definition cannot be modified. Attempting to add new methods to a base class after it has been extended will result in an error. ```lua local Base = LibTSMClass.DefineClass("Base") local Derived = LibTSMClass.DefineClass("Derived", Base) -- Error: Cannot modify Base after it's been subclassed -- function Base:NewMethod() end ``` -------------------------------- ### Get Class Debug String - TSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md The `ToDebugString` method provides a string representation of the class, which is helpful for debugging. The default implementation returns 'class:ClassName'. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") print(MyClass:ToDebugString()) -- prints "class:MyClass" ``` -------------------------------- ### Define and Use Static Method Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md Demonstrates defining a static method using the `__static` accessor and calling it directly on the class. Static methods are class-level functions. ```lua local Math = LibTSMClass.DefineClass("Math") function Math.__static.Add(a, b) return a + b end print(Math.Add(5, 3)) -- prints 8 ``` -------------------------------- ### Inherit Static Properties Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/static-members.md Static properties are inherited by subclasses, but modifications to these properties on a subclass do not affect the base class or other subclasses. Each subclass gets its own copy upon modification. ```lua local Base = LibTSMClass.DefineClass("Base") Base.config = { timeout = 5000 } local Derived = LibTSMClass.DefineClass("Derived", Base) print(Base.config.timeout) -- prints 5000 print(Derived.config.timeout) -- prints 5000 (inherited) -- Modifying on one class doesn't affect the other Derived.config = { timeout = 10000 } print(Base.config.timeout) -- prints 5000 (unchanged) print(Derived.config.timeout) -- prints 10000 ``` -------------------------------- ### Inheritance and Polymorphism in Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/README.md Demonstrates subclassing 'Person' to create an 'Employee' class, overriding methods, and calling parent constructors using LibTSMClass. ```lua -- Create subclass local Employee = LibTSMClass.DefineClass("Employee", Person) function Employee:__init(name, age, jobTitle) self.__super:__init(name, age) -- Call parent constructor self.jobTitle = jobTitle end function Employee:GetInfo() return self.__super:GetInfo() .. " who works as a " .. self.jobTitle end -- Virtual methods resolve to the actual instance type local employee = Employee("Bob", 25, "Engineer") print(employee:GetInfo()) -- prints "Bob is 25 years old who works as a Engineer" ``` -------------------------------- ### Provide Clear Error Messages in Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/best-practices.md When an error occurs, include contextual information in the error message to aid debugging. This example shows checking for a required argument and its type. ```lua function DataStore:Load(filename) if not filename then error("Load() requires a filename argument", 2) end if type(filename) ~= "string" then error("Load() expects filename to be a string, got: " .. type(filename), 2) end -- Continue loading... end ``` -------------------------------- ### Define and Use Classes with LibTSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/README.md Demonstrates defining a base class 'MyClass' and a subclass 'MySubClass' with inheritance and method overriding. Instantiate objects and call methods to manipulate and retrieve values. ```lua local LibTSMClass = LibStub("LibTSMClass") local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass:__init(value) sself._value = value end function MyClass:GetValue() return self._value end function MyClass:SetValue(value) sself._value = value end local MySubClass = LibTSMClass.DefineClass("MySubClass", MyClass) function MySubClass:AddValue(value) sself:SetValue(self:GetValue() + value) end local obj = MySubClass(4) print(obj:GetValue()) -- 4 obj:SetValue(10) print(obj:GetValue()) -- 10 obj:AddValue(5) print(obj:GetValue()) -- 15 ``` -------------------------------- ### Access Static Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/access-control.md Static methods defined with access control modifiers are enforced when called through the library's mechanism. This example shows accessing a static method that is allowed. ```lua local Config = LibTSMClass.DefineClass("Config") function Config.__static.GetSecret() return "secret_value" end print(Config.GetSecret()) -- allowed ``` -------------------------------- ### Attempting to Override Method in Extension (Error) Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/extensions.md This example demonstrates that attempting to override an existing method within a LibTSMClass extension will result in an error. Use inheritance for method overriding. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass:ExistingMethod() return "original" end local ext = MyClass:__extend() -- This raises an error - cannot override existing method -- function ext:ExistingMethod() -- return "override" -- end ``` -------------------------------- ### Virtual Method Resolution with __index Metamethod Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/implementation-details.md Demonstrates the implementation of virtual methods using the __index metamethod. This lookup mechanism walks up the actual instance's inheritance chain to find the correct method. ```lua __index = function(self, key) -- ... check instance fields first ... -- Look up method on actual instance class local class = instInfo.currentClass or instInfo.class local classInfo = private.classInfo[class] -- Search the class and its superclasses while class do local res = classInfo.static[key] if res then return res -- Found method, return it end class = classInfo.superclass classInfo = private.classInfo[class] or {} end end ``` -------------------------------- ### Instantiate a Class Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/Docs/features.md Call the defined class as a function to create an instance. Alternatively, use `LibTSMClass.ConstructWithTable()` to convert an existing table into a class instance. ```lua local classInst = MyClass() ``` ```lua local tbl = { existingValue = 2 } local classInst = LibTSMClass.ConstructWithTable(tbl, MyClass) print(classInst.existingValue) -- prints 2 ``` -------------------------------- ### Attempting to Access Private Method in Extension (Error) Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/extensions.md This example illustrates that extensions in LibTSMClass cannot access private or protected methods of the class. Such methods should be made public or included in the class definition. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass.__private:InternalMethod() return "internal" end local ext = MyClass:__extend() function ext:ExtensionMethod() -- Error: cannot call private method from extension -- return self:InternalMethod() end ``` -------------------------------- ### Factory Methods for Instance Creation Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/static-members.md Implement static methods as factory functions to create and return new instances of a class, often with predefined configurations. ```lua local Point = LibTSMClass.DefineClass("Point") function Point:__init(x, y) self.x = x self.y = y end function Point.__static.Origin() return Point(0, 0) end function Point.__static.FromPolar(r, theta) return Point(r * math.cos(theta), r * math.sin(theta)) end local origin = Point.Origin() print(origin.x, origin.y) -- prints 0, 0 local p = Point.FromPolar(5, math.pi / 4) print(p.x, p.y) -- prints ~3.54, ~3.54 ``` -------------------------------- ### Basic Table Conversion to Class Instance Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/ConstructWithTable.md Converts an existing table into an instance of a specified class. The constructor (`__init`) runs after the table is converted, and existing keys are accessible as instance fields. ```lua local LibTSMClass = LibStub("LibTSMClass") local Person = LibTSMClass.DefineClass("Person") function Person:__init() -- Constructor runs after the table is converted end function Person:GetName() return self.name end -- Convert an existing table to a Person instance local existingData = { name = "Charlie", age = 35 } local person = LibTSMClass.ConstructWithTable(existingData, Person) print(person:GetName()) -- prints "Charlie" print(person.age) -- prints 35 ``` -------------------------------- ### Method Overriding Example in Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/inheritance-and-polymorphism.md Demonstrates how a subclass (Circle) can override a method (GetArea) from its parent class (Shape). Ensure the subclass method has the same name and signature as the parent's method to override it. ```lua local Shape = LibTSMClass.DefineClass("Shape") function Shape:GetArea() return 0 end local Circle = LibTSMClass.DefineClass("Circle", Shape) function Circle:__init(radius) self.radius = radius end function Circle:GetArea() return 3.14159 * self.radius * self.radius end local circle = Circle(5) print(circle:GetArea()) -- prints 78.53975 (not 0) ``` -------------------------------- ### Access Registered Library via LibStub Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/implementation-details.md Demonstrates how to access a library that has been registered with LibStub, enabling its use in other parts of the application. ```lua local LibTSMClass = LibStub("LibTSMClass") ``` -------------------------------- ### Protected Virtual Methods with Access Control Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Virtual-Methods.md Demonstrates how protected virtual methods are called through an instance, respecting access control. Attempting to call a protected method directly will result in an error. ```lua local Base = LibTSMClass.DefineClass("Base") function Base.__protected:Implement() return "base" end function Base:Call() return self:Implement() -- Virtual call to protected method end local Derived = LibTSMClass.DefineClass("Derived", Base) function Derived.__protected:Implement() return "derived" end local inst = Derived() print(inst:Call()) -- prints "derived" (virtual, respects access control) -- inst:Implement() -- Error: protected method ``` -------------------------------- ### DefineClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/MANIFEST.md Defines a new class with specified properties, methods, and modifiers. Supports detailed parameter documentation, return type specification, behavior description, and error handling, with multiple practical examples. ```APIDOC ## DefineClass ### Description Defines a new class with specified properties, methods, and modifiers. Supports detailed parameter documentation, return type specification, behavior description, and error handling, with multiple practical examples. ### Function Signature `DefineClass(className, properties, methods, modifiers)` ### Parameters - **className** (string) - Required - The name of the class to define. - **properties** (table) - Optional - A table of properties for the class. - **methods** (table) - Optional - A table of methods for the class. - **modifiers** (table) - Optional - A table of modifiers to apply to the class (e.g., abstract, final). ### Return Value - (Class) - The newly defined class. ### Error Handling - Documents trigger conditions and how to catch/handle errors. ### Examples - 4+ practical examples demonstrating usage. ``` -------------------------------- ### Define and Subclass Classes with Type Annotations Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/README.md Demonstrates how to define a base class and a subclass using LibTSMClass. Includes type annotations for Lua Language Server compatibility, ensuring correct type inference for class instances. ```lua ---@type Class local MyClass = LibTSMClass.DefineClass("MyClass") ---@type Class local SubClass = LibTSMClass.DefineClass("SubClass", MyClass) local inst = SubClass() -- Type inferred as SubClass ``` -------------------------------- ### Access Control Validation at Call Time Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/access-control.md Access control is validated at call time, not definition time. This example demonstrates an error occurring when attempting to call a private method directly from outside the class. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass.__private:Secret() return 1 end local inst = MyClass() -- Error happens when calling, not when defining: local status = pcall(function() inst:Secret() end) -- status is false: "Attempting to call private method (...)" ``` -------------------------------- ### Create a Class Extension Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/extensions.md Use the `__extend()` method on a class to create an extension object, then add new methods to this extension. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass:ExistingMethod() return "original" end -- Create an extension local ext = MyClass:__extend() -- Add methods to the extension function ext:NewMethod() return "new feature" end function ext:AnotherMethod() return "more features" end ``` -------------------------------- ### Virtual Method Resolution with Access Control Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/access-control.md Demonstrates how virtual method calls respect access control. The `Implement` method is called virtually, but its access level is enforced. ```lua local Base = LibTSMClass.DefineClass("Base") function Base.__protected:Implement() return "base" end function Base:Call() return self:Implement() -- virtual call end local Derived = LibTSMClass.DefineClass("Derived", Base) function Derived.__protected:Implement() return "derived" end local inst = Derived() print(inst:Call()) -- prints "derived" (virtual + access control respected) ``` -------------------------------- ### Constructor Chaining Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/inheritance-and-polymorphism.md Demonstrates constructor chaining by calling the parent constructor first. This ensures proper initialization of inherited properties before subclass-specific initialization. ```lua local Animal = LibTSMClass.DefineClass("Animal") function Animal:__init(name) self.name = name self.alive = true end local Dog = LibTSMClass.DefineClass("Dog", Animal) function Dog:__init(name, breed) self.__super:__init(name) -- Initialize parent first self.breed = breed end local dog = Dog("Buddy", "Labrador") print(dog.name) -- prints "Buddy" print(dog.breed) -- prints "Labrador" ``` -------------------------------- ### Enforcing Access Control with inClassFunc Counter Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/access-control.md LibTSMClass uses an `inClassFunc` counter to track execution context. Access control checks validate this counter. This example shows a protected method being called successfully from within a public method, but would fail if called directly from outside. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass.__protected:ProtectedMethod() return "protected" end function MyClass:PublicMethod() -- Within this method: inClassFunc > 0 return self:ProtectedMethod() -- allowed end -- After returning: inClassFunc == 0 local inst = MyClass() inst:PublicMethod() -- allowed: calls through public method -- inst:ProtectedMethod() -- Error: inClassFunc == 0 ``` -------------------------------- ### ConstructWithTable Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/ConstructWithTable.md Constructs an instance of a class using an existing table, preserving the table's keys as instance fields. This is useful when you have pre-populated data that should become a class instance. The provided table is converted in-place, and the class's `__init()` method is called with the provided arguments. ```APIDOC ## ConstructWithTable ### Description Constructs an instance of a class using an existing table, preserving the table's keys as instance fields. This is useful when you have pre-populated data that should become a class instance. The provided table is converted in-place, and the class's `__init()` method is called with the provided arguments. ### Signature ```lua function Lib.ConstructWithTable(tbl: table, class: table, ...: any): table ``` ### Parameters #### Path Parameters - **tbl** (table) - Required - A table containing pre-existing key-value pairs to preserve as instance fields - **class** (table) - Required - The class to instantiate - **...** (any) - Optional - Arguments to pass to the class's `__init()` constructor ### Return Type Returns an **instance** of the specified class. The returned instance is the same table object passed as `tbl` but with the class metatable applied and its fields processed through the instance metamethods. ### Behavior - The provided table is converted to a class instance in-place - All existing keys in the table are preserved and treated as instance fields - The class's `__init()` method is called with the provided arguments after the metatable is applied - All keys are re-set through the `__newindex` metamethod to ensure proper access control and field storage - If the class has a superclass, instance fields are stored in a separate fields table; otherwise they are stored directly on the instance ### Throws - Constructor-related errors from the class's `__init()` method - Standard class instantiation errors if abstract methods are not implemented - Internal assertion error if the table is not properly converted (should never occur in normal usage) ### Examples #### Basic Table Conversion ```lua local LibTSMClass = LibStub("LibTSMClass") local Person = LibTSMClass.DefineClass("Person") function Person:__init() -- Constructor runs after the table is converted end function Person:GetName() return self.name end -- Convert an existing table to a Person instance local existingData = { name = "Charlie", age = 35 } local person = LibTSMClass.ConstructWithTable(existingData, Person) print(person:GetName()) -- prints "Charlie" print(person.age) -- prints 35 ``` #### Preserving Existing Data with Constructor Arguments ```lua local Item = LibTSMClass.DefineClass("Item") function Item:__init(rarity) self.rarity = rarity if not self.quality then self.quality = "normal" end end function Item:GetDescription() return "Item: " .. self.name .. " (" .. self.quality .. ", rarity: " .. self.rarity .. ")" end -- Start with existing data and add constructor-time initialization local itemData = { name = "Sword of Power" } local item = LibTSMClass.ConstructWithTable(itemData, Item, "rare") print(item:GetDescription()) -- prints "Item: Sword of Power (normal, rarity: rare)" ``` #### Converting Nested Tables ```lua local Config = LibTSMClass.DefineClass("Config") function Config:__init() -- Post-construction initialization end function Config:GetValue(key) return self[key] end -- Convert a complex table local configData = { apiUrl = "https://api.example.com", timeout = 5000, retries = 3, features = { cache = true, logging = false } } local config = LibTSMClass.ConstructWithTable(configData, Config) print(config:GetValue("apiUrl")) -- prints "https://api.example.com" print(config:GetValue("timeout")) -- prints 5000 print(config.features.cache) -- prints true ``` #### Identity Preservation with Inheritance ```lua local Base = LibTSMClass.DefineClass("Base") function Base:__init(x) self.x = x end local Derived = LibTSMClass.DefineClass("Derived", Base) function Derived:__init(x, y) self.__super:__init(x) self.y = y end -- The returned table is the same object as the input local tbl = { y = 20 } local derived = LibTSMClass.ConstructWithTable(tbl, Derived, 10) print(derived == tbl) -- prints true (same object) print(derived.x) -- prints 10 print(derived.y) -- prints 20 ``` ### Notes - This function is primarily useful for deserializing data or working with tables that already exist in memory - The provided table must be empty or contain only valid instance field data—it should not have metamethods of its own - After conversion, the table is fully managed by the class system - For classes without a superclass, fields are stored directly on the instance table for better performance; for classes with inheritance, a separate fields table is used - The same instance is returned (identity is preserved), so `derived == tbl` is true ``` -------------------------------- ### Class Instantiation Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md Creates a new instance of a class by calling the class itself. Arguments are passed to the instance's `__init()` method. This method can throw errors if the class is abstract, if the `__init()` method fails, or if required abstract methods are not implemented. ```APIDOC ## Class Instantiation ### `class(...)` — Constructor Call ```lua function class(...): instance ``` Calling a class as a function creates a new instance of that class. **Parameters:** - `...` — Arguments to pass to the instance's `__init()` method **Return Type:** instance **Throws:** - Error if the class is abstract - Errors from the `__init()` method - Error if required abstract methods are not implemented **Example:** ```lua local Person = LibTSMClass.DefineClass("Person") function Person:__init(name) self.name = name end local p = Person("Alice") -- class() is called automatically ``` ``` -------------------------------- ### Implement Class Constructor Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/Docs/features.md The `__init()` method serves as the constructor, called during class instantiation. It initializes instance properties and should not return any values. ```lua function MyClass:__init(value) self._value = value end function MyClass:GetValue() return self._value end local classInst = MyClass(42) print(classInst:GetValue()) -- prints 42 ``` -------------------------------- ### Implementing Abstract Methods in LibTSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/Docs/features.md Illustrates how abstract classes can define methods that subclasses must implement. Abstract methods are implicitly protected and must be overridden using the `__protected` metamethod. ```lua function AbstractClass.__abstract:_GetResult() end function AbstractClass:AddNumber(num) return num + self:_GetResult() end function ImplClass.__protected:_GetResult() return 10 end local inst = ImplClass() print(inst:AddNumber(2)) -- prints 12 ``` -------------------------------- ### Instantiate a Class - TSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Class-Methods.md Call a class as a function to create a new instance. Arguments are passed to the instance's `__init()` method. Ensure the class is not abstract and all required abstract methods are implemented. ```lua local Person = LibTSMClass.DefineClass("Person") function Person:__init(name) self.name = name end local p = Person("Alice") -- class() is called automatically ``` -------------------------------- ### Abstract Classes and Methods in Lua Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/README.md Demonstrates defining an abstract class 'Animal' and a concrete subclass 'Dog' that implements the abstract method. Abstract classes cannot be instantiated directly. ```lua -- Define abstract class local Animal = LibTSMClass.DefineClass("Animal", nil, "ABSTRACT") -- Abstract methods must be implemented by subclasses function Animal.__abstract:MakeSound() end -- Concrete implementation local Dog = LibTSMClass.DefineClass("Dog", Animal) function Dog.__protected:MakeSound() return "Woof!" end -- Cannot instantiate Animal directly -- local animal = Animal() -- Error local dog = Dog() ``` -------------------------------- ### Defining Abstract Classes in LibTSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/Docs/features.md Shows how to define an abstract class by passing 'ABSTRACT' as the third argument to DefineClass. Abstract classes cannot be instantiated directly but can be subclassed. ```lua local AbstractClass = LibTSMClass.DefineClass("AbstractClass", nil, "ABSTRACT") local ImplClass = LibTSMClass.DefineClass("ImplClass", AbstractClass) ``` -------------------------------- ### Instance Not Found Debug Info Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/GetDebugInfo.md Illustrates the behavior when GetDebugInfo is called with an instance string that does not correspond to any known instance. In such cases, the function returns nil. ```lua -- If the instance string doesn't match any known instance, returns nil local debugInfo = LibTSMClass.GetDebugInfo("NonExistent:00000000", 2) print(debugInfo) -- prints nil ``` -------------------------------- ### Registry Pattern for Instance Management Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/static-members.md Employ static members to maintain a registry (e.g., a table) of class instances, allowing retrieval by a unique key. ```lua local Service = LibTSMClass.DefineClass("Service") Service.registry = {} function Service:__init(name) self.name = name Service.registry[name] = self end function Service.__static.Get(name) return Service.registry[name] end function Service.__static.ListAll() local names = {} for name in pairs(Service.registry) do table.insert(names, name) end return names end local svc1 = Service("auth") local svc2 = Service("database") print(Service.Get("auth") == svc1) -- prints true print(table.concat(Service.ListAll(), ", ")) -- prints "auth, database" ``` -------------------------------- ### Document Lua Public Methods with Return Values Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/best-practices.md Document public methods by specifying their return types and a description of what is returned. ```lua -- Document public methods --[[ GetUsername(): string Returns the user's username. Returns: The username string ]] function User:GetUsername() return self.username end ``` -------------------------------- ### __tostring() Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Instance-Methods.md Returns a string representation of the instance. The default implementation can be overridden. ```APIDOC ## __tostring() ### Description Returns a string representation of the instance. Default implementation returns `"ClassName:HEXADDRESS"` but can be overridden. ### Signature `function instance:__tostring(): string` ### Return Type string ### Example ```lua local Item = LibTSMClass.DefineClass("Item") function Item:__init(name) self.name = name end function Item:__tostring() return "Item(" .. self.name .. ")" end local item = Item("Sword") print(item) -- prints "Item(Sword)" print(tostring(item)) -- prints "Item(Sword)" ``` ``` -------------------------------- ### Use Descriptive Names for Static Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/best-practices.md Name static factory methods and utility functions descriptively to clearly indicate their purpose. ```lua function User.__static.CreateFromJSON(json) -- Implementation end function Logger.__static.GetInstance() -- Singleton access end ``` -------------------------------- ### Add Extension Method to Instances Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/implementation-details.md Demonstrates how methods added via the extension mechanism are applied to all existing class instances. This ensures immediate availability of new functionality. ```lua -- When a method is added via extension: classInfo.static[key] = value for inst in pairs(classInfo.instances) do rawset(inst, key, value) -- Add directly to instance (no superclass) end ``` -------------------------------- ### Define and Use Static Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/static-members.md Define static methods using the `__static` accessor. These methods are called directly on the class. ```lua local Math = LibTSMClass.DefineClass("Math") function Math.__static.Add(a, b) return a + b end function Math.__static.Multiply(a, b) return a * b end print(Math.Add(5, 3)) -- prints 8 print(Math.Multiply(5, 3)) -- prints 15 ``` -------------------------------- ### Instance Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/MANIFEST.md Details on the methods available for instances of classes within the Tradeskillmaster library. ```APIDOC ## Instance Methods ### __init() - **Description**: Initializes an instance. - **Status**: Complete ### __tostring() - **Description**: Returns a string representation of the instance. - **Status**: Complete ### __equals() - **Description**: Compares the instance with another object for equality. - **Status**: Complete ### __dump() - **Description**: Dumps the instance's data. - **Status**: Complete ### __isa() - **Description**: Checks if the instance is of a specific type. - **Status**: Complete ### __as() - **Description**: Casts the instance to a specific type. - **Status**: Complete ### __closure() - **Description**: Returns the closure of the instance. - **Status**: Complete ### ToDebugString() - **Description**: Returns a debug string representation of the instance. - **Status**: Complete ``` -------------------------------- ### Wrapped Instance Method Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/implementation-details.md Shows how an original instance method is wrapped to enable virtual method resolution and access control. This wrapping updates the instance's current method class, increments access control counters, and calls the original method via a helper function. ```lua -- Original method defined as: function MyClass:PublicMethod() return 42 end -- Gets wrapped to: classInfo.static[key] = function(inst, ...) -- Update instance's current method class instInfo.methodClass = MyClass -- Increment inClassFunc counter (for access control validation) tempMethodClassInfo = MyClass while tempMethodClassInfo do tempMethodClassInfo.inClassFunc = tempMethodClassInfo.inClassFunc + 1 tempMethodClassInfo = tempMethodClassInfo.superclass end -- Call the original method return InstMethodReturnHelper(previousClass, instInfo, MyClass, originalFunc(inst, ...)) end ``` -------------------------------- ### Access Parent Constructor and Methods with `__super` Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/inheritance-and-polymorphism.md Shows how to call the parent class's constructor and methods from within a derived class's instance methods using `self.__super`. ```lua local Animal = LibTSMClass.DefineClass("Animal") function Animal:__init(name) self.name = name end function Animal:Speak() return "Some sound" end local Dog = LibTSMClass.DefineClass("Dog", Animal) function Dog:__init(name, breed) self.__super:__init(name) -- Call parent constructor self.breed = breed end function Dog:Speak() return self.__super:Speak() .. " (woof)" -- Call parent method end local dog = Dog("Buddy", "Labrador") print(dog:Speak()) -- prints "Some sound (woof)" ``` -------------------------------- ### Temporary Table Reuse Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/implementation-details.md Demonstrates the pattern for reusing a temporary table to minimize memory allocation overhead and reduce garbage collection pressure. Asserts that the table is empty before use and wipes it after. ```lua assert(not next(private.tempTable)) -- Ensure it's empty -- Use the table... wipe(private.tempTable) -- Clear for reuse ``` -------------------------------- ### Virtual Methods vs. Callbacks in LibTSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/Virtual-Methods.md Illustrates the preferred virtual method approach for defining polymorphic behavior compared to a less clean callback-based implementation. Use virtual methods for cleaner, more object-oriented designs. ```lua -- Using virtual methods (preferred) local Logger = LibTSMClass.DefineClass("Logger") function Logger:Log(message) print("[LOG] " .. message) end local DebugLogger = LibTSMClass.DefineClass("DebugLogger", Logger) function DebugLogger:Log(message) print("[DEBUG] " .. os.date("%H:%M:%S") .. " " .. message) end -- Using callbacks (not as clean) local CallbackLogger = {} function CallbackLogger.new(logFunc) return { logFunc = logFunc, Log = function(self, msg) self:logFunc(msg) end } end ``` -------------------------------- ### Adding Serialization Methods to Config Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/extensions.md Extends a Config class with `ToJSON` to serialize settings into a JSON string. A basic `FromJSON` is also included as a placeholder. ```lua local Config = LibTSMClass.DefineClass("Config") function Config:__init() self.settings = {} end function Config:Set(key, value) self.settings[key] = value end local ext = Config:__extend() function ext:ToJSON() local json = "{" for k, v in pairs(self.settings) do json = json .. '"' .. k .. '":"' .. tostring(v) .. '",' end json = json:gsub(",$", "") -- Remove trailing comma json = json .. "}" return json end function ext:FromJSON(jsonStr) -- Simple parsing (production code would be more robust) -- This is just an example end local config = Config() config:Set("apiUrl", "https://api.example.com") config:Set("timeout", "5000") print(config:ToJSON()) -- prints {"apiUrl":"https://api.example.com","timeout":"5000"} ``` -------------------------------- ### Converting Nested Tables to Class Instance Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/api-reference/ConstructWithTable.md Demonstrates converting a table with nested structures into a class instance. Nested tables are preserved as fields on the instance. ```lua local Config = LibTSMClass.DefineClass("Config") function Config:__init() -- Post-construction initialization end function Config:GetValue(key) return self[key] end -- Convert a complex table local configData = { apiUrl = "https://api.example.com", timeout = 5000, retries = 3, features = { cache = true, logging = false } } local config = LibTSMClass.ConstructWithTable(configData, Config) print(config:GetValue("apiUrl")) -- prints "https://api.example.com" print(config:GetValue("timeout")) -- prints 5000 print(config.features.cache) -- prints true ``` -------------------------------- ### Access Parent Class Properties and Static Methods Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/inheritance-and-polymorphism.md Illustrates how to access class-level properties and static methods of a parent class using `Derived.__super.propertyName`. ```lua local Base = LibTSMClass.DefineClass("Base") Base.version = "1.0" local Derived = LibTSMClass.DefineClass("Derived", Base) Derived.version = "2.0" print(Base.version) -- prints "1.0" print(Derived.version) -- prints "2.0" print(Derived.__super.version) -- prints "1.0" (accesses parent) ``` -------------------------------- ### Public Method Usage in LibTSMClass Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/access-control.md Demonstrates calling a public method on an instance of a class defined with LibTSMClass. ```lua local MyClass = LibTSMClass.DefineClass("MyClass") function MyClass:PublicMethod() return "accessible" end local inst = MyClass() print(inst:PublicMethod()) -- allowed ``` -------------------------------- ### Define Class Names with PascalCase Source: https://github.com/tradeskillmaster/libtsmclass/blob/main/_autodocs/best-practices.md Use PascalCase for defining class names to ensure consistency and readability. ```lua local User = LibTSMClass.DefineClass("User") local DataStore = LibTSMClass.DefineClass("DataStore") local EventEmitter = LibTSMClass.DefineClass("EventEmitter") ```