private
読み:ぷらいべーと
外語:private
C++/Javaなどの予約語の一つで、メンバーへのアクセス指定を行なう。また、そういったメンバーのこと。
概要
まず逆に、privateではないメンバーは、他のクラスからも呼び出すことができる。対してprivateなメンバーは、定義しているクラス内からしか参照することができない。
C++ではラベルのように用い、書いた場所以降のメンバー変数やメンバー関数に影響するが、Javaではそれぞれのフィールドやメソッドに個別に指定しなければならない。
プログラミング言語によっては当初存在せず、後から拡張するにあたり独特の方法を採用するものもある(例: ECMAScript)。
特徴
C++の継承
C++ではクラスを継承する際の指定としても用いることができる。その場合、基底クラスの全てのメンバー変数/関数はprivate扱いになる。つまり、継承したクラスでは参照できなくなる。
class hasei : private kihon {
}
classのデフォルトの継承はprivate継承、structのデフォルトの継承はpublicである。
private継承の使い道はほぼ無いが、基底クラスの実装を再利用したいがそのメンバーは使わせたくない、という限られた場面では使われることがある(かもしれない)。
派生クラスからのアクセス
JavaではC++のような継承方法は存在しないため、C++で言うところのpublic継承に相当する動きになると期待される。
この時に継承したクラス(派生クラス)から基底クラスにアクセスした場合、publicとprotectedのメンバーにはアクセス可能で、privateのメンバーは派生クラスからでもアクセスできない。
補足
C++の場合
C++の場合はラベルのように使い、それ以降に定義されたものに影響する。public、protected、privateと3種類あるアクセス制限の一つで、何も書かなければデフォルト状態でpublicである。
class A {
int pub;
private:
int priv;
};
このように定義された場合、クラス外からprivateのメンバーにはアクセスできない。
A a;
a.pub = 123; // OK
a.priv = 123; // エラー
Javaの場合
C++の影響を受けて作られたJavaもC++と同様にpublic、protected、privateと3種類あるアクセス制限の一つだが、使い方が全く異なり修飾子と用いられる。
class A {
public int pub;
private int priv;
};
このように定義された場合、クラス外からprivateのメンバーにはアクセスできない。
A a = new A();
a.pub = 123; // OK
a.priv = 123; // エラー
ECMAScriptの場合
ECMAScript(いわゆるJavaScript)は元々privateメンバーは存在しなかった。
と言うより、そもそも当初のJavaScriptにclassという概念自体存在しない。JavaScriptという言語は大規模なプログラミングなどそもそも想定されておらず、varで変数を定義し関数スコープ(またはグローバルスコープ)になるような言語だったのである。
classが追加されたのはECMAScript 2015からだが、ここでもprivateメンバーという仕様は定義されなかった。ようやく追加されたのがECMAScript 2022からである。
しかしJavaのようにprivateという予約語を新規追加する仕様にはならなかった。いくつか理由はあるが、後から予約語を新規追加する場合は既存の実装も考慮する必要がある。実際、稼働中のJavaScript実装ではprivate修飾子があってもエラーにもならず無視してそのままpublicフィールドを作るものがあったそうである。これは潜在的なバグの原因となりうるため、検討の末private修飾子の追加案は避けられた。
そこで変数名の頭に記号を付け足すというアイディアが出された。色々な記号が模索され、当初は@を付ける案が有力だったが、同時期に仕様検討されていたDecoratorsで使うためにそちらに譲った。しかし使える残された記号は少なく、アンダースコア(_)は既存のJavaScriptコードとの互換性問題を起こすことが確実、また%、^、&、? などの記号は演算子と混同されうるので避けられた。結果消去法で # を変数名やメソッド名の頭に付ける仕様となった。
class A {
pub = 0;
#priv = 1;
m() {
return this.pub + this.#priv;
}
}
ECMAScriptでは、privateなメンバーにアクセスするためには this.#name のようにthis.を付ける必要がある。
TypeScriptの場合
ECMAScriptで仕様が決まるよりも前、altJSの一つであるTypeScriptではJavaと同様にprivate修飾子に対応していた。
TypeScriptはECMAScript(JavaScript)にコンパイルされる言語だが、コンパイラーがprivate修飾子をチェックしてスコープ外からのアクセスを弾いた上で、出力されるECMAScriptは普通の(publicな)メンバーである。理由は簡単で当時のECMAScriptにprivateメンバーは存在しないからである。
現在のTypeScriptでは#によるprivateメンバーにも対応し、コンパイルするECMAScriptのバージョンごとに挙動が変化する。
#のprivateはその仕様上ランタイムでチェックされ、private修飾子はコンパイラーでチェックされるという違いがある。
再検索