TypeScript 基底クラス アクセス
TypeScriptで基底クラスのメンバにアクセスする
TypeScriptでは、派生クラスから基底クラスのメンバにアクセスすることができます。このアクセス方法は、基底クラスのメンバが protected
または public
で宣言されている場合に有効です。
protected メンバへのアクセス
- 例
- 派生クラスでの直接アクセス
protected
メンバは、派生クラス内から直接アクセスすることができます。
class Base {
protected name: string;
constructor(name: string) {
this.name = name;
}
}
class Derived extends Base {
greet() {
console.log("Hello, " + this.name); // Direct access to protected member
}
}
public メンバへのアクセス
class Base {
public age: number;
constructor(age: number) {
this.age = age;
}
}
class Derived extends Base {
getAge() {
return this.age; // Direct access to public member
}
}
class Base {
private secret: string;
constructor(secret: string) {
this.secret = secret;
}
}
class Derived extends Base {
// Cannot access secret directly
}
注意
private
メンバは、宣言されたクラス内でのみアクセスできます。public
メンバは、任意のクラスからアクセスできます。protected
メンバは、派生クラスと基底クラス内でアクセスできます。
TypeScriptにおける基底クラスのメンバアクセス:コード例解説
基礎知識
- アクセス修飾子
メンバ(プロパティやメソッド)へのアクセスを制御するキーワードです。TypeScriptでは、主にpublic
,protected
,private
が使用されます。 - 派生クラス
基底クラスを継承したクラス。子クラスとも呼ばれます。 - 基底クラス
他のクラスが継承する、元のクラス。親クラスとも呼ばれます。
コード例解説
class Animal {
protected name: string;
constructor(name: string) {
this.name = name;
}
protected move() {
console.log(`${this.name}が動きます。`);
}
}
class Dog extends Animal {
bark() {
console.log('ワンワン!');
this.move(); // protected メンバである move() を呼び出せる
}
}
const myDog = new Dog('ポチ');
myDog.bark();
- 解説
Animal
クラスが基底クラス、Dog
クラスが派生クラスです。name
とmove
メソッドはprotected
なので、Animal
クラス自身と、それを継承するDog
クラス内からのみアクセスできます。Dog
クラスのbark
メソッド内で、基底クラスのmove
メソッドを呼び出しています。
class Person {
public name: string;
public age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
}
class Student extends Perso n {
study() {
console.log(`${this.name}は勉強しています。`);
}
}
const taro = new Student('太郎', 20);
console.log(taro.name); // public なので、外部から直接アクセスできる
taro.study();
- 解説
Person
クラスが基底クラス、Student
クラスが派生クラスです。name
とage
はpublic
なので、どのクラスからもアクセスできます。
class Person {
private id: number; // private なので、外部からアクセスできない
constructor(id: number) {
this.id = id;
}
}
class Employee extends Person {
// id に直接アクセスすることはできない
}
- 解説
- private
クラス内部でのみアクセス可能。データの隠蔽性を高め、意図しない変更を防ぎます。 - public
どこからでもアクセス可能。外部から自由に操作できるプロパティやメソッドに適しています。 - protected
派生クラスからアクセス可能。基底クラスの実装を隠蔽しつつ、派生クラスに機能を拡張させる際に役立ちます。
重要なポイント
- カプセル化
private
を効果的に利用することで、クラス内部のロジックを隠蔽し、外部からの影響を受けにくくすることができます。 - アクセス修飾子の選択
メンバの可視性を適切に設定することで、コードの保守性と安全性向上に繋がります。 - 継承の原則
派生クラスは、基底クラスの機能を拡張し、新しい機能を追加するものです。
- ミックスイン
複数のクラスの機能を組み合わせるためのテクニックです。 - 抽象クラス
抽象メソッドを含むクラスで、具体的な実装を持たないメソッドを定義できます。 - TypeScriptのインターフェース
型定義を厳密に行うことができ、コードの信頼性を高めます。
TypeScriptの継承は、大規模なアプリケーション開発において、コードの再利用性と保守性を高める上で非常に重要な概念です。
上記の説明は、TypeScriptにおける基底クラスのメンバアクセスに関する基本的な概念を解説したものです。より深い理解のためには、以下の点についても学習することをお勧めします。
- ポリモーフィズム
異なる型のオブジェクトを同じように扱うことができる性質です。 - オーバーライド
基底クラスのメソッドを派生クラスで再定義することです。 - superキーワード
基底クラスのコンストラクタやメソッドを呼び出す際に使用します。
これらの概念を組み合わせることで、より柔軟で拡張性の高いオブジェクト指向プログラミングが可能になります。
[キーワード]
TypeScript, 基底クラス, 派生クラス, アクセス修飾子, protected, public, private, 継承, オブジェクト指向プログラミング
- ポリモーフィズムのメリットは何ですか?
- TypeScriptで抽象クラスとインターフェースの違いは何ですか?
インターフェースによる抽象化
- 利点
- 基底クラスのメンバの型を定義し、派生クラスに強制することができます。
- 柔軟性と再利用性を向上させることができます。
interface Animal {
name: string;
move(): void;
}
class Dog implements Animal {
constructor(public name: string) {}
move() {
console.log(`${this.name}が走ります。`);
}
}
ミックスイン
- 利点
- 複数のクラスから機能を組み合わせることができます。
function Flyable(constructor: new () => any) {
return class extends constructor {
fly() {
console.log('飛んでいます。');
}
};
}
class Bird {
constructor(public name: string) {}
}
const FlyingBird = Flyable(Bird);
const eagle = new FlyingBird('ワシ');
eagle.fly();
委譲
class Animal {
constructor(public name: string) {}
move() {
console.log(`${this.name}が動きます。`);
}
}
class Dog {
private animal: Animal;
constructor(name: string) {
this.animal = new Animal(name);
}
bark() {
console.log('ワンワン!');
this.animal.move();
}
}
ジェネリクス
- 利点
class Base<T> {
protected data: T;
constructor(data: T) {
this.data = data;
}
}
class Derived extends Base<string> {
// ...
}
デコレーター
- 利点
function Loggable(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
console.lo g(`Calling ${propertyKey} with args: ${args}`);
return originalMethod.apply(this, args);
};
return descriptor;
}
class MyClass {
@Loggable
method() {
// ...
}
}
typescript