アクセス修飾子 (access modifier)
JavaやPHPなどの言語では、フィールドやメソッドにprivate
, protected
, public
を指定できます。JavaScriptでもprivate
のようなプロパティを実現するためにプライベートクラスフィールドという仕様がありますが、Javaのようなアクセス修飾子とはやや様相が異なります。TypeScriptにはJava風のアクセス修飾子があります。
アクセス修飾子 | 説明 |
---|---|
(宣言なし) | publicと同等 |
public | どこからもアクセス可能 |
protected | 自身のクラスとサブクラスからアクセス可能 |
private | 自身のクラスのみアクセス可能 |
アクセス修飾子を省略した場合はpublic
になります。
アクセス修飾子は、フィールド、コンストラクタ、メソッドに宣言することができます。
public
public
アクセス修飾子はどこからもアクセス可能です。アクセス修飾子を省略した場合もpublic
を指定したものと同等として扱われます。
ts
classAnimal {publicname : string; // フィールドにpublicアクセス修飾子// コンストラクターにpublicアクセス修飾子public constructor(theName : string) {this.name =theName ;}// メソッドにpublicアクセス修飾子publicmove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);// publicアクセス修飾子である`this.name`を使用することが可能}}
ts
classAnimal {publicname : string; // フィールドにpublicアクセス修飾子// コンストラクターにpublicアクセス修飾子public constructor(theName : string) {this.name =theName ;}// メソッドにpublicアクセス修飾子publicmove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);// publicアクセス修飾子である`this.name`を使用することが可能}}
gorilla
を実装し、動作を確認してみます。
ts
constgorilla = newAnimal ("ゴリラ");gorilla .move (10);gorilla .name = "ゴリラゴリラ";gorilla .move (20);
ts
constgorilla = newAnimal ("ゴリラ");gorilla .move (10);gorilla .name = "ゴリラゴリラ";gorilla .move (20);
name
プロパティはpublic
宣言されているため、インスタンスされた変数(gorilla
)からの読み書きが可能になっています。「ゴリラ」から「ゴリラゴリラ」に変更することができます。
protected
protected
アクセス修飾子は自身のクラスとサブクラスからアクセス可能です。
Animal
クラスmove
メソッドのアクセス修飾子をpublic
からprotected
に変更しエラーを出してみます。
ts
classAnimal {publicname : string;public constructor(theName : string) {this.name =theName ;}// `public`から`protected`に変更protectedmove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);}}constgorilla = newAnimal ("ゴリラ");Property 'move' is protected and only accessible within class 'Animal' and its subclasses.2445Property 'move' is protected and only accessible within class 'Animal' and its subclasses.gorilla .(10); move
ts
classAnimal {publicname : string;public constructor(theName : string) {this.name =theName ;}// `public`から`protected`に変更protectedmove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);}}constgorilla = newAnimal ("ゴリラ");Property 'move' is protected and only accessible within class 'Animal' and its subclasses.2445Property 'move' is protected and only accessible within class 'Animal' and its subclasses.gorilla .(10); move
gorilla.move()
メソッドはprotected
宣言されているため、自身のクラスとサブクラスのみアクセスとなります。つまりインスタンスされたgorilla
からはアクセスが拒否され、コンパイルエラーが発生します。
protected
で保護されたmove()
メソッドを新たに実装し、10倍速く動くゴリラを作ってみます。
ts
classAnimal {publicname : string;public constructor(theName : string) {this.name =theName ;}// `public`から`protected`に変更protectedmove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);}}classGorilla extendsAnimal {move (distanceInMeters : number) {super.move (distanceInMeters * 10);}}constgorilla = newGorilla ("速いゴリラ");gorilla .move (10);
ts
classAnimal {publicname : string;public constructor(theName : string) {this.name =theName ;}// `public`から`protected`に変更protectedmove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);}}classGorilla extendsAnimal {move (distanceInMeters : number) {super.move (distanceInMeters * 10);}}constgorilla = newGorilla ("速いゴリラ");gorilla .move (10);
Animal
スーパークラスを持つGorilla
クラスを定義しmove()
を実装しています。Gorilla
クラスのmove()
メソッド内でsuper
キーワードを利用してスーパークラスのmove()
メソッドを呼び出しています。
private
private
アクセス修飾子は自身のクラスのみアクセス可能です。
protected move()
をprivate move()
に変更してみます。private
に変更されたことによりGorilla
クラスのsuper.move
にアクセスすることが許されずエラーとなります。
ts
classAnimal {publicname : string;public constructor(theName : string) {this.name =theName ;}// `public`から`private`に変更privatemove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);}}classClass 'Gorilla' incorrectly extends base class 'Animal'. Property 'move' is private in type 'Animal' but not in type 'Gorilla'.2415Class 'Gorilla' incorrectly extends base class 'Animal'. Property 'move' is private in type 'Animal' but not in type 'Gorilla'.extends Gorilla Animal {move (distanceInMeters : number) {super.Property 'move' is private and only accessible within class 'Animal'.2341Property 'move' is private and only accessible within class 'Animal'.( move distanceInMeters * 10);}}
ts
classAnimal {publicname : string;public constructor(theName : string) {this.name =theName ;}// `public`から`private`に変更privatemove (distanceInMeters : number) {console .log (`${this.name } moved ${distanceInMeters }m.`);}}classClass 'Gorilla' incorrectly extends base class 'Animal'. Property 'move' is private in type 'Animal' but not in type 'Gorilla'.2415Class 'Gorilla' incorrectly extends base class 'Animal'. Property 'move' is private in type 'Animal' but not in type 'Gorilla'.extends Gorilla Animal {move (distanceInMeters : number) {super.Property 'move' is private and only accessible within class 'Animal'.2341Property 'move' is private and only accessible within class 'Animal'.* 10); move (distanceInMeters }}
private
メソッドの多くの使い方としては、自身のクラス内の長いコードを機能別に分ける時に利用します。
アクセス修飾子を変更する
クラスの継承時に、メソッドのアクセス修飾子を変更することができます。とはいえなんでも自由に変更できるのではなく、アクセス制限を緩める方向にだけ変更できます。つまりprotected
> public
の方向への変更は可能ですがその逆はできません。
ts
classProtectedClass {protecteddoNothing (): void {console .log ("DO NOTHING");}}classPublicClass extendsProtectedClass {publicdoNothing (): void {console .log ("DO NOTHING");}}
ts
classProtectedClass {protecteddoNothing (): void {console .log ("DO NOTHING");}}classPublicClass extendsProtectedClass {publicdoNothing (): void {console .log ("DO NOTHING");}}
逆のpublic
> protected
の実装はできません。
ts
classPublicClass {publicdoNothing (): void {console .log ("DO NOTHING");}}classClass 'ProtectedClass' incorrectly extends base class 'PublicClass'. Property 'doNothing' is protected in type 'ProtectedClass' but public in type 'PublicClass'.2415Class 'ProtectedClass' incorrectly extends base class 'PublicClass'. Property 'doNothing' is protected in type 'ProtectedClass' but public in type 'PublicClass'.extends ProtectedClass PublicClass {protecteddoNothing (): void {console .log ("DO NOTHING");}}
ts
classPublicClass {publicdoNothing (): void {console .log ("DO NOTHING");}}classClass 'ProtectedClass' incorrectly extends base class 'PublicClass'. Property 'doNothing' is protected in type 'ProtectedClass' but public in type 'PublicClass'.2415Class 'ProtectedClass' incorrectly extends base class 'PublicClass'. Property 'doNothing' is protected in type 'ProtectedClass' but public in type 'PublicClass'.extends ProtectedClass PublicClass {protecteddoNothing (): void {console .log ("DO NOTHING");}}