Rubyで普通に使っていた(というより標準ライブラリにすらArray.[]
とArray#[]
がまったく別目的で定義してあるぐらいの)「インスタンスメソッドと同名のクラスメソッドを作ること」ですが、言語によってできるできないが分かれることに気づきました。
できない言語
PHP
はじめはPHPで似たようなことをやろうとして、行き詰まったところでQiitaの記事にたどり着きました。結局、クラスメソッドもインスタンスメソッドも「同じクラスで定義されるメソッド」なので同名にはできない、ということでした(両方をマジックメソッドで対応するなら別ですが)。
C++
PHPでできなかったところで、C++でも試してみました。
class Foo
{
public:
void hoge() {}
static void hoge() {}
};
int main()
{
return 0;
}
上のプログラムは、コンパイルしただけで
test.cpp:11:17: error: 'static void Foo::hoge()' cannot be overloaded
test.cpp:6:10: error: with 'void Foo::hoge()'
と、エラーになってしまいました。
Java
同じようなことをpaiza.ioでJavaについてもやってみましたが、やはり「error: method foo() is already defined in class Hoge」とのことでした。
まとめ
クラスメソッドを「そのクラスに属するstatic
なメソッド」とする言語では、static
でないものと同じ名前(と、言語によってはシグネチャ)だと衝突してしまう、という感じでした。
できる言語
Ruby
Rubyの場合、「クラスメソッド」=「(何らかの方法で)クラスオブジェクトに生やすメソッド」なので、インスタンスのメソッドとはそもそも別系統になります。
TypeScript
となると、「クラス」がオブジェクトとして存在しているTypeScriptだとどうなるだろう、と気になって試してみることにしました。
// TypeScript
class Test{
foo() { }
static foo() { }
}
// JavaScriptへの翻訳後
var Test = (function () {
function Test() {
}
Test.prototype.foo = function () { };
Test.foo = function () { };
return Test;
}());
と、「クラスメソッド=オブジェクト自身に生えるメソッド」「インスタンスメソッド=prototype
のメソッド」ということがはっきりしています。