Why can I never use self?

function BreadServer:UpdateCharacterBread(Player)
	print(1)
end

BuyItem.OnServerEvent:Connect(function(Player, ItemType, Item)
	self:UpdateCharacterBread(Player)
end)

self has a red underline saying Unknown Global self

2 Likes

Self can only be used within a method that uses the syntax “:”.

Let’s say you have an object(table).
You can add a method to that object by doing function object:Test()
self will refer to object(whatever object this function is a method of)
End

1 Like

self will not necessarily always refer to object. It will refer to the first argument passed to the function. These two constructions are identical:

function t:f(...) end
function t.f(self, ...) end

These two calls are identical:

t:f(123)
t.f(t, 123)

The implicit self variable is only created when constructing a function with the : syntax.

12 Likes

self is mainly used as part of object oriented programming. You can make a self variable by creating a virtual object then referencing it / a function in it’s own scope / meta scope

1 Like

So really this an illustration of Static vs Non-Static methods/variables. Other some other languages make you explicitly define methods as (non)/static but since Lua OOP is more of a simulation of OOP through tables there is nothing/no reason to build that kind of syntax into it and the line becomes blurred.

For example say you had the following code

function BreadServer.New(Data)
    local self = setmetatable({},BreadServer); --Nothing special about this, just a syntax choice
    self.Data = Data;
    return Data;
end

function BreadServer:PrintData()
    print(self.Data);
end

function BreadServer:TestingMethod()
    print("Testing");
end

In this case the PrintData method would be a non-static method because it requires the variable self to run but TestingMethod could be either depending on where you call it from. For example is a ServerScript

local Bread = require(BreadServer);

local BreadInstance = Bread.New("LETS GET THIS BREAD");

BreadInstance:TestingMethod();--NonStatic Call
Bread:TestingMethod();--Static Call

Both would work but if you called

Bread:PrintData();
--Rather than
BreadInstance:PrintData();

Your code would error because in the first case, the bread object was not instantiated and thus did not have a reference self. It’s a little difficult to wrap your head around how it works in Lua just because of how weird it ends up being, but if you look into/play around with java you will have a much more clear picture.

In your case to fix your code you could just throw the event connection into the Instantiation method something like.

function BreadServer.New()
    local self = setmetatable({},BreadServer);
    --Code Stuff
    BuyItem.OnServerEvent:Connect(function(Player, ItemType, Item)
    self:UpdateCharacterBread(Player)
    end)
end

--Just keep in mind there is no distinguishment there so every remote event will cause every bread server to be updated
3 Likes

Don’t do this. This only hurts readability and conveys the wrong idea about Lua OOP. If a method is static/just a function just define it with a ., and real methods with a :.

3 Likes

What are you talking about? That’s perfectly fine…

BreadServer is the object created, TestingMethod is the method inside the object.

No, that “method” never references “self”, which means it’s just a regular function/static method. Dot syntax is preferred to express this message.

1 Like

That method never references self but any methods subsequently called inside it will still have access to the path…

Like I said, this is fine.

If it calls a method within itself then it will be using self to do self:method, at which point it would be a method. But in the example provided it isn’t, and should use dot syntax.

I still stand by what I said. You wont want simple math forumlas and such that don’t reference self inside of a method but the method shown is still fine to me. Swithching between methods and paths would made the code harder to debug and could cause later problems.

The function is intended to be a method, that’s also shown by the name “TestingMethod” so it shouldn’t be changed. Not just for how it’s written now but for future in-case any additional methods are added in-line with it.

1 Like

self isn’t in the scope of the event, it would only work if you moved the end to below the event. I’m not really sure why you would do that though because it would just be creating multiple events that do the same thing.

This is completely wrong and is evident if you’ve used other languages than Lua too. The static vs non static concept is still very much a thing in Lua and not following it leads to lack of ability to infer things about functions without having to look at their source.

Like I’m saying, even though self isn’t referenced in the example, as it’s intentended to be a method, this method will most likely alter the object directly in future. I did say that you wouldn’t use it for simple formulas that don’t reference self, but this example is intended to be a method.

It’s true that you wouldn’t have that as a method as it is now but if the intention / futre intention is for it to alter the object directly, it’s fine.

I’m not considering that as a finished method, what I’m saying is that it’s fine for future edits / subsequent methods that use self which I mentioned in my second post.

Your code example is using self in place of any regular variable; this does not make code look cleaner and it is not what self is intended for either. If anything it would confuse the reader.

3 Likes

I’m aware that this isn’t the most appropriate way to use it, but I used it as an example to simplify on what capabilities self has in Lua programming.

It does not show capabilities of self in any way. Simplifying something by not using it properly is not helping anyone.

function getRobuxIndexInATable( t )
   return t.Robux
end

is identical to what you wrote and much clearer.

If you wish to showcase the capability of self (it really doesn’t have many, it’s mostly syntactic sugar) then you ought to show the usage in OO or it isn’t showing anything;

https://www.lua.org/pil/16.html

1 Like

This isn’t very performant because if you want to create an instance of an object, you’re wasting memory and computation unnecessarily. This is why you see methods defined in their own module-level table so often, so that they can be reused.

This and the post linked below will explain everything to you about OOP (Object Orientated Programming) read them carefully.

2 Likes