はじめに
Robloxでは、関数やメソッドを呼び出すときに「:」と「.」の2種類の書き方があります。
見た目は似ていますが、self を自動で渡すかどうかが大きな違いです。
「:」は自分自身を自動で渡す
たとえば、ModuleScript で次のように関数を定義できます。
local TestModule = {}
function TestModule:MyPrint1(text)
print(`MyPrint1(:) {text} {self}`)
end
return TestModule
この : を使った書き方は、内部的には次のように書いたのと同じ意味になります。
function TestModule.MyPrint1(self, text)
print(`MyPrint1(:) {text} {self}`)
end
つまり、: で関数を定義すると、第1引数として self が自動的に受け取られると考えると分かりやすいです。
呼び出すときも同じで、次の2つは同じように動きます。
TestModule:MyPrint1("Hello1")
TestModule.MyPrint1(TestModule, "Hello2")
どちらも、self には TestModule が入ります。
「.」は自分で引数を渡す
次は . を使った書き方です。
local TestModule = {}
function TestModule.MyPrint2(self, text)
print(`MyPrint2(.) {text} {self}`)
end
return TestModule
この書き方では、self は自動では入りません。
そのため、呼び出すときに自分で self を渡す必要があります。
local TestModule = require(script.Parent.TestModule)
TestModule.MyPrint2(TestModule, "Hello1")
このように書けば、 self に TestModule が入り、: で呼び出したときと同じ結果になります。
実行結果のイメージ
たとえば、次のように呼び出したとします。
local TestModule = require(script.Parent.TestModule)
TestModule:MyPrint1("Hello1")
TestModule.MyPrint1(TestModule, "Hello2")
TestModule.MyPrint2(TestModule, "Hello1")
TestModule.MyPrint2(TestModule, "Hello2")
出力結果:
MyPrint1(:) Hello1 table: 0x2f5603616ca3100a
MyPrint1(:) Hello2 table: 0x2f5603616ca3100a
MyPrint2(.) Hello1 table: 0x2f5603616ca3100a
MyPrint2(.) Hello2 table: 0x2f5603616ca3100a
このとき、self にはどの場合も TestModule が入るため、出力される内容は同じようになります。
table: 0x... のように全部同じアドレスなのは、同じテーブルを参照しているためです。
まとめ
関数を自作するときは、次のように覚えると分かりやすいです。
-
:を使うと、selfを自動で受け取れる。 -
.を使うと、selfを自分で渡す必要がある。 - メソッドとして使うなら
:、普通の関数として使うなら.と考えると分かりやすい。
: での呼び出しは、「第1引数に自分自身を付け足して実行する」という挙動が面白いですね。