TypeScript独学---第四章:類
8253 ワード
クラス#クラス#
次にクラスの使用を見てください
3つの部分の1つは
継承
派生クラスには、ベースクラスのコンストラクション関数を実行する
パブリック、プライベート、保護された修飾子
public
TypeScriptでは、メンバーのデフォルトは
private
メンバーが
protected
コンストラクタは
readonly修飾子
パラメータのプロパティ
前の段落をパラメータプロパティで変更します.次のようになります.
パラメータ属性は、コンストラクション関数パラメータの前にアクセス制限子を追加することによって宣言されます.
アクセス装置
アクセサのないコード
注意
静的プロパティ
静的プロパティはクラスにのみ存在し、クラスのインスタンスには存在しません.
抽象クラス
抽象クラスは、他の派生クラスのベースクラスとして使用されます.一般的には、インスタンス化されません.
抽象クラスの抽象メソッドには、特定の実装は含まれず、派生クラスで実装する必要があります.抽象メソッドの構文はインタフェースメソッドと似ています.どちらもメソッド署名を定義しますが、メソッドボディは含まれません.しかしながら、抽象的な方法は、
高度なテクニック
コンストラクタ
クラスにはインスタンス部分と静的部分の2つの部分があると考えられる.この例を少し書き直して、違いを見てみましょう.
クラスをインタフェースとして使用する
次にクラスの使用を見てください
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
let greeter = new Greeter("world");
3つの部分の1つは
greeting
という属性であり、1つの構造関数と1つのgreet
方法である.継承
class Animal {
name:string
constructor(theName:string){
this.name = theName
}
move(distanceInMeters:number = 0){
console.log(`${this.name} moved ${distanceInMeters}.`)
}
}
class Snake extends Animal {
constructor(name:string){
super(name)
}
move(distanceInMeters = 5){
console.log("Slithering...")
super.move(distanceInMeters) // move
}
}
class Horse extends Animal {
constructor(name:string){
super(name)
}
move(distanceInMeters = 45){
console.log("Galloping...")
super.move(distanceInMeters)
}
}
let sam = New Snake("Sammy the Python")
let tom:Animal = new Horse("Tommy the Palomino")
sam.move()
tom.move(34)
派生クラスには、ベースクラスのコンストラクション関数を実行する
super()
を呼び出すコンストラクション関数が含まれています.コンストラクタでthisプロパティにアクセスするには、super()
を呼び出す必要があります.また、この例ではmove
メソッドも書き換えられています.//
Slithering...
Sammy the Python moved 5m.
Galloping...
Tommy the Palomino moved 34m.
パブリック、プライベート、保護された修飾子
public
TypeScriptでは、メンバーのデフォルトは
public
です.このように書くこともできますclass Animal {
public name: string;
public constructor(theName: string) { this.name = theName; }
public move(distanceInMeters: number) {
console.log(`${this.name} moved ${distanceInMeters}m.`);
}
}
private
メンバーが
private
とマークされている場合、クラスを宣言する外部アクセスはできません.class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // : 'name' .
protected
protected
修飾子は、private
修飾子の動作と似ていますが、protected
メンバーは派生クラスにアクセスできます.class Person {
protected name: string;
constructor(name: string) { this.name = name; }
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name)
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
console.log(howard.getElevatorPitch());
console.log(howard.name); //
コンストラクタは
protected
としてマークすることもできる.では、このクラスは継承できますが、インスタンス化できません.class Person {
protected name: string;
protected constructor(theName: string) { this.name = theName; }
}
// Employee Person
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}
let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // : 'Person' .
readonly修飾子
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // ! name .
パラメータのプロパティ
前の段落をパラメータプロパティで変更します.次のようになります.
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {
}
}
パラメータ属性は、コンストラクション関数パラメータの前にアクセス制限子を追加することによって宣言されます.
private
を使用してパラメータ属性を定義すると、プライベートメンバーが宣言され、初期化されます.public
およびprotected
についても同様である.アクセス装置
アクセサのないコード
class Employee {
fullName: string;
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
console.log(employee.fullName);
}
set
メソッドとget
メソッドlet passcode = "secret passcode";
class Employee {
private _fullName: string;
get fullName(): string {
return this._fullName;
}
set fullName(newName: string) {
if (passcode && passcode == "secret passcode") {
this._fullName = newName;
} else {
console.log("Error: Unauthorized update of employee!");
}
}
}
let employee = new Employee();
employee.fullName = "Bob Smith";
if (employee.fullName) {
alert(employee.fullName);
}
注意
get
のみを有し、set
を有しないアクセサは、readonly
と自動的に推定される.静的プロパティ
静的プロパティはクラスにのみ存在し、クラスのインスタンスには存在しません.
class Grid {
static origin = { x: 0, y: 0 };
calculateDistanceFromOrigin(point: { x: number; y: number }) {
let xDist = point.x - Grid.origin.x;
let yDist = point.y - Grid.origin.y;
return Math.sqrt(xDist * xDist + yDist * yDist) / this.scale;
}
constructor(public scale: number) {}
}
let grid1 = new Grid(1.0); // 1x scale
let grid2 = new Grid(5.0); // 5x scale
console.log(grid1.calculateDistanceFromOrigin({ x: 10, y: 10 }));
console.log(grid2.calculateDistanceFromOrigin({ x: 10, y: 10 }));
static
を使用してorigin
を定義します.これは、すべてのグリッドで使用されるプロパティです.各インスタンスがこのプロパティにアクセスするには、origin
の前にクラス名を付けます.すなわち、Grid.
は、静的属性にアクセスする.抽象クラス
抽象クラスは、他の派生クラスのベースクラスとして使用されます.一般的には、インスタンス化されません.
abstract class Animal {
abstract makeSound(): void;
move(): void {
console.log("roaming the earch...");
}
}
抽象クラスの抽象メソッドには、特定の実装は含まれず、派生クラスで実装する必要があります.抽象メソッドの構文はインタフェースメソッドと似ています.どちらもメソッド署名を定義しますが、メソッドボディは含まれません.しかしながら、抽象的な方法は、
abstract
キーワードを含み、アクセス修飾子を含むことができる.abstract class Department {
constructor(public name: string) {}
printName(): void {
console.log("Department name: " + this.name);
}
abstract printMeeting(): void; //
}
class AccountingDepartment extends Department {
constructor() {
super("Accounting and Auditing"); // super()
}
printMeeting(): void {
console.log("The Accounting Department meets each Monday at 10am.");
}
generateReports(): void {
console.log("Generating accounting reports...");
}
}
let department: Department; //
department = new Department(); // :
department = new AccountingDepartment(); //
department.printName();
department.printMeeting();
department.generateReports(); // :
高度なテクニック
コンストラクタ
// ts
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return 'Hello, ' + this.greeting;
}
}
let greeter: Greeter;
greeter = new Greeter('world');
console.log(greeter.greet());
// JS
let Greeter = (function() {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function() {
return 'Hello, ' + this.greeting;
};
return Greeter;
})();
let greeter;
greeter = new Greeter('world');
console.log(greeter.greet());
クラスにはインスタンス部分と静的部分の2つの部分があると考えられる.この例を少し書き直して、違いを見てみましょう.
class Greeter {
static standardGreeting = 'Hello, there';
greeting: string;
greet() {
if (this.greeting) {
return 'Hello, ' + this.greeting;
} else {
return Greeter.standardGreeting;
}
}
}
let greeter1: Greeter;
greeter1 = new Greeter();
console.log(greeter1.greet());
let greeterMaker: typeof Greeter = Greeter;
greeterMaker.standardGreeting = 'Hey there!';
let greeter2: Greeter = new greeterMaker();
console.log(greeter2.greet());
クラスをインタフェースとして使用する
class Point {
x: number;
y: number;
}
interface Point3d extends Point {
z: number;
}
let point3d: Point3d = {x: 1, y: 2, z: 3};