なぜ "static" メンバと呼ぶか

ALGOL の基本的な構造化エンティティはブロックです。Cで言えばブレス「{}」で囲まれたアレですね。ブロックには幾つかのデータ定義が含まれ、その後ろにデータを操作するコードが続きます。ブロック内でローカル変数を宣言することによって、活性化レコードを定義することが出来ます*1
ブロックに入ると、そのローカル変数が使用するメモリ空間を持つ活性化レコードが、自動的に実行時スタックの上に作成されます。非常に便利な仕組みなのですが、残念ながらコレには一つ大きな欠点があって、プロックを抜けるとき、レコードやそのローカル変数が値と一緒に削除されてしまうのです。

この欠陥(!?)が認められ、ALGOLのスーパーセットとして別の言語が開発されました。その言語は「ローカル変数を持った手続き」から、「出入りとは無関係に活性化できるレコード」へ、構造の概念をより一般化したものでした。それが かのSimula で、一般化された構造をクラス、その活性化レコードをオブジェクトと呼んだのです*2


――と、言うのは オブジェクト指向言語のはなし の受け売り。実はあたしは Simula について全く詳しくありません(^^;) あしからず。この「ブロック(≒関数)を一般化するとクラスになる」という考え方にあたしはいたく感動したのでした。

C の ローカル変数は、言語的には 自動変数 と呼んで、キーワード auto で作ります(何もつけないと勝手に auto になる)。一方、活性化レコードの生成と関係なしに使える ローカル変数には static というキーワードをつけます。このキーワードの名前が良いか悪いは別として(悪いよなぁ)、ブロック内の static キーワード付き変数に、多くの人は(静的に領域が確保される変数というよりは)ブロックの活性化と関係なしに使用できる変数という「概念」を描いていると思います。たぶん。(自動変数を「ブロックに入ったときに自動的に領域確保され、自動的に破棄される関数」と字面どおりの概念として頭に描いている人は、多分少ないように)

クラスの活性化レコードをオブジェクトといい、「クラスのインスタンス」とも言います。元々この考え方だと「データ定義とそれを操作するコード」と「それを実行する為の活性化レコード」であるため、ベーシックな考え方としてはクラスメソッド、クラスフィールドという概念をもちません。が、Cの関数に static変数 という、関数そのものに紐づけられたデータエンティティがあるように、クラスにそのものに紐づけられたエンティティがあってもいいはずだし、便利です。それが C++ の静的メンバ変数と 静的メンバ関数で、static という語は、(良いネーミングかどうかを別にして)Cの関数のキーワードモデルと一貫性があります。

本家と元祖 もしくは 会長派と社長派

Smalltalk 文化圏の、「クラスもオブジェクトなんだから自分のためのメソッド・フィールドを持つのは当然」と C++ 文化圏の 「関数: static変数 = クラス : staticメンバ」 という方向論でも、結局、使う側にしてみれば細かいことです。あたしの周辺だけで判断するのはアレなんですが、C++ でも C# でも 「静的メンバ関数」なんて「言って」る人は滅多にいません。「クラスメソッド」の方がやっぱり 言葉としてわかりやすいし言いやすい。

「static」は抽象度の低い言葉ですが、「クラスメソッド」と「静的メンバ関数」の用語の対比が背負ってるモノは、(「static」と言う用語のしっちゃかめっちゃかさ加減もあって)現状では「実際に静的にメモリ上に確保されるか」よりもその言語の系譜と概念モデル(思想)に深く結びついているように感じます*3

同じようなこだわりに this と self だとか、map と collect だとか。こういう話を論じるのは楽しいのだけれど、身のある結果は出ない話題でもありますね。

*1:Cマニアにとって、ローカル変数は関数の頭じゃなくってブロックの頭で作れるんだぜ、という突っ込みは至福の瞬間

*2:最初はプロセスとアクションと呼んでいたらしい

*3:C#とかの用語は露骨にC++ 言語圏ですよという主張だし。それにインスタンスメソッドだって、別にインスタンスオブジェクト生成時に確保されるわけじゃないですし(つまりその意味では静的に(^^;)、既に C++ の時点で static の「静的メモリ確保」ぽい意味なんて蒸発しちゃってると思います。