プログラミングにおけるスコープとは
プログラミングにおける
スコープ(scope, 可視範囲)とは、変数や関数などの名前(
識別子)が参照できる範囲のことを指します。通常、変数や関数が定義されたスコープの外側からは、それらの名前を用いるだけでは参照できません。このとき、これらの変数や関数は「スコープ外」である、あるいは「見えない」といわれます。
スコープの重要性
プログラミングでは、ソースコードの可読性を向上させ、予期しない誤動作を避けるため、それぞれの処理段階で必要のない要素の名前はできるだけ参照されないようにすることが望ましいです。
特に、複数の関数にまたがったスコープを持つことができる
グローバル変数(大域変数)は便利な場合もありますが、どこで参照・変更されているかを常に気にしていなければならず、不用意な変更は危険でもあります。そのため、変数の有効範囲を最小限にすることが推奨されています。
スコープと生存期間
スコープは、名前の可視性や名前解決について議論される概念です。一方、
生存期間(lifetime)は、オブジェクトの有効期間やライフサイクルについて議論される概念です。例えば、
C言語において、関数内の
ローカル変数に`static`キーワードを付加すると、その変数の可視範囲は関数内のままですが、生存期間は変化します。
スコープと生存期間は異なる概念ですが、
動的スコープのように、両者が混同される場合もあります。
スコープの種類
スコープは、その適用範囲や導入方法によって、いくつかの種類に分類されます。
大域スコープ (global scope)
プログラム全体から見えるスコープです。このスコープに属する変数は、
グローバル変数または大域変数と呼ばれます。
BASICのような単純な言語では大域スコープしか存在しない場合があります。
Pythonのように
グローバル変数の書き換えが簡単に行えない言語も存在します。
ファイルスコープ (file scope)
大域スコープと似ていますが、プログラムを記述したファイルの内側でのみ参照できるスコープです。プログラムが複数のファイルから構成される場合は、他のファイルから参照することはできません。
局所スコープ (local scope)
ある関数やブロックの範囲内に限定されたスコープです。このスコープに属する変数は、
ローカル変数と呼ばれます。一般に入れ子のローカルスコープは外側を参照できますが、兄弟関係にあるスコープは見えません。
C言語や
C++では、内側のブロックで外側のブロックと同じ名前の
識別子を定義できますが、
JavaやC#では許可されません。
インスタンススコープ (instance scope)
クラスベースのオブジェクト指向言語で、クラスの各インスタンスに割り当てられた変数(フィールド)や関数(メソッド)が、そのインスタンス経由でのみ参照できるスコープです。インスタンス内で共有されるので、局所スコープよりも可視範囲が広くなります。
C言語の
構造体メンバー参照も一種のインスタンススコープです。
クラススコープ (class scope)
クラスベースのオブジェクト指向言語で、あるクラスの定義全体から参照できるスコープです。クラス全体で共有されるため、ある種の制限された大域スコープと考えることもできます。
クラススコープを持たない言語でも、ファイルスコープを用いることで同様の機構を実現できる場合があります。
オブジェクト指向言語は通常、
カプセル化のため、アクセス修飾子によってアクセス可能な範囲を制限できますが、アクセス修飾子とスコープの概念は別物です。
スコープ導入からの分類
静的スコープ (static scope)
字句スコープまたはレキシカルスコープとも呼ばれます。ブロックや関数などの入れ子構造によって静的に可視範囲が導入されるスコープです。
動的スコープ (dynamic scope)
実行時の動的な呼び出しの親子関係によって導入されるスコープです。関数が呼び出し元で展開されたかのようなスコープが構成されます。実行時に名前による解決が必要なため、コンパイルが複雑になります。
名前空間 (namespace)
厳密には
名前空間自体はスコープそのものではなく、スコープを導入する機構です。
名前の集合を定義し、任意のタイミングで
名前空間を導入し、定義された名前を参照可能にすることができます。
名前空間では持続範囲を指定できるため、外部で必要のない名前の拡散を避けることもできます。
名前空間自体も一種のスコープを持ち、
名前空間の名前によって参照されます。
ファイルスコープやローカルスコープも、暗黙の
名前空間でスコープを構成していると考えることができます。
構造体のメンバー名のように、他の名前と干渉せずに使用できる空間を
名前空間と呼びます。
まとめ
スコープは、プログラミングにおいて非常に重要な概念です。スコープを正しく理解し、適切に利用することで、可読性の高い、バグの少ないコードを作成することができます。様々な種類のスコープについて理解を深め、より良いプログラミングを目指しましょう。