OOP: Mimicking Instance.new()

Hello! I got into OOP just about yesterday, and I’m wondering how I can mimic Instance.new(). Specifically, how it can create different objects with its first argument (class name). While I’ve been able to create new classes and such (e.g. Bullet.new(), Dodgeball.new(), and Rock.new()), what are some ways I can simply this? Using multilple module scripts? I kind of want to have it more like Projectile.new(string className), much like Instance.new(), although I don’t really know of a way to go about this.

Of course, there’s numerous tutorials that cover OOP, but I’ve haven’t found any that documents super classes, sub classes, etc very well.

Super classes aren’t really part of Roblox OOP. Metatables are, for the most part, just a very basic OOP system.

Before I get started, you might consider using NexusInstance if you are looking to have more functionality with your objects, similar to what you might find in a language like Java or C++.

If you want to replicate this with sub classes, the easiest way would be to have a module script which just does something like:

Projectile.new(function(class, ...)
    require(script[class]).new(...)
end)

Obviously there are numerous improvements to that code (namely how you could setup something that puts all of your required modules into a dictionary, and then allows you to just do something like modules[class].new(...)). That being said, this still removes alot of functionality you might want to have (though in Lua it’s not as big of a problem as it would be in a language like C++).

Another option is to make Projectile something like an abstract class, and then have all of the classes which extend from it look like:

local ProjectileExtended = {}
ProjectileExtended.__index = function(index)
    if ProjectileExtended[index] then
        return ProjectileExtended[index]
    elseif Projectile[index] then
        return Projectile[index]
    end
end

Do the same thing listed above with the Projectile class’s constructor, but setup the Projectile to have all the methods you want.

As for keeping variables you might setup in your Projectile class, you would need to have some sort of hidden constructor like:

Projectile._new(function()
    local self = setmetatable({}, Projectile)
    
    -- setup variables of self

    return self
end)

which could then be accessed by your other classes like:

ProjectileExtended.new(function()
    local self = setmetatable(Projectile._new(), ProjectileExtended)

    -- setup ProjectileExtended variables

    return self
end)

This way you have all of the main classes functionality, which you are extending from. Obviously this isn’t fully extending classes since it is still missing super, and so forth, but it is a fairly good start. There’s alot more that you can do, but at that point I really just recommend using NexusInstance since you would otherwise be pretty much just remaking the wheel.

Hope this helps!

2 Likes

Thank you! This helps so much. Do you use Nexus Instance yourself?

Depending on what I need, I will use either normal metatables, or NexusInstance.

If I just need a basic Class, that I will never need to extend from, or which won’t need the various things it (NexusInstance) offers, I will just use metatables.

If I need more complex OOP things, I will use NexusInstance.