Giter Club home page Giter Club logo

simploo's Introduction

SIMPLOO 2.1.4 - Simple Lua Object Orientation


Introduction

SIMPLOO is a library for the Lua programming language. Its goal is to simplify class based object-oriented programming inside Lua.

Lua is generally considered to be prototype-based language, which means that it's possible to define individual objects with their own states and behaviors. However, more advanced concepts such as inheritance and encapsulations are harder to achieve because Lua lacks the syntax to formally express these concepts.

The general workaround for these limitations is to modify the behavior of the object itself to include these concepts instead of relying on the language. Unfortunately this is often challenging and time consuming, especially when you have many different types of objects and behaviors.

This library is designed to help with this process by using the freedom of Lua to emulate the same class-based programming syntax that's so often seen in other languages. After you've provided a class definition you can easily derive new objects from it, and SIMPLOO will handle everything that's required to make your objects behave the way you'd expect.

Example

Here's an initial impression of the library.

-------------
-- Syntax 1
-- looks like normal Lua
-------------

local diagonal = class("Diagonal", {namespace = "math.trigonometry"})

function diagonal.public.static:calculate(width, height)
    return math.sqrt(math.pow(width, 2) + math.pow(height, 2))
end

diagonal:register()

-------------
-- Syntax 2
-- looks more like other languages
-------------

namespace "math.geometry.shapes"
using "math.trigonometry.Diagonal"

class "Rectangle" {
    private {
        m_width = 0;
        m_height = 0;
    };
    public {
        __construct = function(self, initialWidth, initialheight)
            self.m_width = initialWidth
            self.m_height = initialheight
        end;

        getWidth = function(self)
            return self.m_width
        end;

        getHeight = function(self)
            return self.m_height
        end;

        getArea = function(self)
            return self.m_width * self.m_height
        end;

        getDiameter = function(self)
            return Diagonal:calculate(self.m_width, self.m_height);
        end;
    };
}

local square = math.geometry.shapes.Rectangle.new(5, 10)
print(square:getWidth()) -- 5
print(square:getHeight()) -- 10
print(square:getArea()) -- 50
print(square:getDiameter()) -- 11.18034

Features

  • Define classes using a familiar syntax, including keywords such as private, public, abstract, static, const and meta for metamethods.
  • Supports multiple inheritance to define complex relational trees between classes.
  • Supports constructor and finalizer methods (using __gc).
  • Allows you to define your own metamethods for your classes.
  • Support for namespaces.
  • Supports two syntaxes.

Changes compared to 1.0

  • Rewritten and split into multiple files.
  • Support for namespacing to improve your project organisation.
  • Performance has been increased by lowering internal overhead.

Requirements

  • This library has been developed and tested on Lua 5.1, Lua 5.2 and LuaJIT.
  • The availability of the debug library (specifically debug.getupvalue and debug.setupvalue) is only required for Lua 5.2, in order to support the 'using' keyword.

Expectations

This library attempts to emulate classes as closely as possible. However, code is still interpreted in real-time and instantiating a new instance will take a little bit of time - most of it spend on deep copying data.

This means that the library is best used to keep track of long lived objects- for example entities in a game world. It is not suitable for a use case that requires thousands of new objects every seconds, such as networking packets.

Instantiation time scales linearly with the number of attributes, methods and parents that a class has. For function call performance, this library has a 'production mode' setting which makes it bypass all sanity checks. This setting boosts runtime performance significantly.

Benchmarks

AMD Ryzen 7 1800X (~3.6GHz), 3200MHz CL14 DDR4 RAM

Mode Lua 5.1 Lua 5.2 Lua JIT
Development - 10k instantiations 0.871 1.038 0.308
Production - 10k instantiations 0.894 1.048 0.313
Development - 2M fn calls 2.129 2.647 0.547
Production - 2M fn calls 0.619 0.642 0

Performance is by far superior on LuaJIT based environments.

Documentation

Wiki

Feedback

You can submit an issue, create a pull request or contact me directly using the email listed on my profile page.

simploo's People

Contributors

maurits150 avatar

Stargazers

Cqws avatar  avatar Sky.Allen avatar Kevin Morgan avatar AlexanderT avatar Gawehold avatar Phil avatar Jack Trent avatar  avatar Omar Assadi avatar  avatar Michael Binder avatar Song lanlan avatar Theodor Stamati avatar Michael Yuen avatar  avatar George L. Albany avatar Alexandru-Mihai Maftei avatar Kyle avatar Abel avatar Sam Maddock avatar Jesse Savary avatar Bell avatar Alex Swift avatar Adam Burton avatar Mikkel Struntze avatar looter avatar  avatar Alexey Melnichuk avatar Roland avatar

Watchers

 avatar Mikkel Struntze avatar Abel avatar Kyle avatar zloopnew avatar Jack Trent avatar

simploo's Issues

Bug in lua 5.3 with 'unpack'

In lua 5.3 the global function 'unpack' was changed to 'table.unpack'
Code must be modified changing it for Lula 5.3

getters & setters

hey, great work you've done with this! Do you think it's possible to add getters & setters in a clean way?

api might be like

public {
    foobar = {
        get = function(self) print("pop value by getter"); return self.bananna end
        set = function(self, value) print("push value through setter"); self.bananna = value end
    }
};
private {
    bananna = 0
};

and then using like

klass.foobar = klass.foobar + 1 -- updated the private 'bananna' property by the setter
print(klass.foobar) -- '1' returned by getter

Access works by a regular table.property call, but every action (__index, __newindex) is piped through its getter or setter function. So essentially this is like class methods but you can have two methods accessible under one property handle.

Support hotswap of classes.

When reloading a class, existing instances should be hot-swappable with the new codebase.

This should be a config option disabled by default.

It could work by tracking all active instances and, on reload of a class, replace the content of all old instances with the contents of the newer instance, and then copy all members (except methods) from the old instance to the new instance to maintain object state.

Also make sure that storing our list of instances is done weakly, so that it won't prevent __finalize on existing instances either.

  • Newly added members will not be overwritten by the old state and retain their initial class defined values.
  • Removed members simply won't be copied over to the new instance.

We can't call the constructor of the new instance though so it can't initialize new members. Maybe issue a warning when this happens.

We also have to make sure the finalizer on the old instance does not get called when it's hot swapped to prevent things from unloading by accident.

Inheritance

Can you provide an example of class inheritance ( if possible )

I currently have a PhysicsBody class and I have another Wheel class which I need for it to inherit from PhysicsBody.

I'm using the traditional syntax without any namespaces.

class "PhysicsBody" {
    ....
}

class "Wheel" {
    ...
}

default (nil) values not working ?

Hi

I am trying out some things with namespaces and classes and I now come across the following 'problem'. Is this a desired result?

Sometimes I already set some default values, but I don't think it's possible to use a nil value in a table in lua. That is why the error below goes I guess.

class "Frameset" {
    private {
        name = nil -- point 1
        -- name = "" -- point 2 this is the fix (not using a nil value, but a empty string value "")
    },
    public {
    	__construct = function(self, name)
            self.name = name -- not working
            -- self:setName(name) -- not working
            print(self.name) -- nil
            print(name) -- hoi
        end,
        setName = function(self, name)
            self.name = name
        end,
        getName = function(self)
            return self.name
        end
    }
}

test = Frameset.new("hoi")
print(test:getName()) -- nil - because i'm using point 1 above

Bug in ambiguous state of members.

The ambiguity state of member variables isn't being tracked correctly.

class "A" {
    func = function(self)
        print("A called")
    end;
    var = 5;
}

class "B" {
    func = function(self)
        print("B called")
    end;
    var = 10;
}

class "C" extends "A, B" {
    hi = function(self)
        self.A:func() -- Should WORK!
        print(self.A.var) -- Should WORK!

        self.B:func() -- Should WORK!
        print(self.B.var) -- Should WORK!

        self:func() -- Should CRASH with ambiguous
        print(self.var)-- Should CRASH with ambiguous
    end;
}

C.new():hi()

but it actually crashes on line self.B:func().

private not working as expected

I am using Simploo V2 and what is happening is private properties are able to be referenced in instances rather than just the class itself.

Should this be happening because I thought private properties could not be accessed like an instance member outside of the class?

namespace "Game"

class "Instance" {
    public {};

    private {
        Testing = "Accessed";
    };
}

local x = Game.Instance:new()
print(x.Testing);
-- > Returns "Accessed"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.