アクセス修飾子 (access modifier)
JavaやPHPなどの言語では、フィールドやメソッドにprivate, protected, publicを指定できます。JavaScriptでもprivateのようなプロパティを実現するためにプライベートクラスフィールドという仕様がありますが、Javaのようなアクセス修飾子とはやや様相が異なります。TypeScriptにはJava風のアクセス修飾子があります。
| アクセス修飾子 | 説明 |
|---|---|
| (宣言なし) | publicと同等 |
| public | どこからもアクセス可能 |
| protected | 自身のクラスとサブクラスからアクセス可能 |
| private | 自身のクラスのみアクセス可能 |
アクセス修飾子を省略した場合はpublicになります。
アクセス修飾子は、フィールド、コンストラクタ、メソッドに宣言することができます。
public
publicアクセス修飾子はどこからもアクセス可能です。アクセス修飾子を省略した場合もpublicを指定したものと同等として扱われます。
tsclassAnimal {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`を使用することが可能}}
tsclassAnimal {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を実装し、動作を確認してみます。
tsconstgorilla = newAnimal ("ゴリラ");gorilla .move (10);gorilla .name = "ゴリラゴリラ";gorilla .move (20);
tsconstgorilla = newAnimal ("ゴリラ");gorilla .move (10);gorilla .name = "ゴリラゴリラ";gorilla .move (20);
nameプロパティはpublic宣言されているため、インスタンスされた変数(gorilla)からの読み書きが可能になっています。「ゴリラ」から「ゴリラゴリラ」に変更することができます。
protected
protectedアクセス修飾子は自身のクラスとサブクラスからアクセス可能です。
Animalクラスmoveメソッドのアクセス修飾子をpublicからprotectedに変更しエラーを出してみます。
tsclassAnimal {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
tsclassAnimal {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倍速く動くゴリラを作ってみます。
tsclassAnimal {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);
tsclassAnimal {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にアクセスすることが許されずエラーとなります。
tsclassAnimal {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);}}
tsclassAnimal {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の方向への変更は可能ですがその逆はできません。
tsclassProtectedClass {protecteddoNothing (): void {console .log ("DO NOTHING");}}classPublicClass extendsProtectedClass {publicdoNothing (): void {console .log ("DO NOTHING");}}
tsclassProtectedClass {protecteddoNothing (): void {console .log ("DO NOTHING");}}classPublicClass extendsProtectedClass {publicdoNothing (): void {console .log ("DO NOTHING");}}
逆のpublic > protectedの実装はできません。
tsclassPublicClass {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");}}
tsclassPublicClass {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");}}