サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

TypeScript入門 05: get/setアクセサをを使う


get/setアクセサを使うと、メソッドをプロパティのように参照して扱えます。読み取り専用プロパティとして定めたり、値の設定時に他のプロパティを処理するなど、単純なプロパティにはできない機能が加えられます。

01 getアクセサを使う

本稿は、「TypeScriptTypeScript入門 04: オブジェクト型リテラルとインタフェースを使う」で書いたコード002「オブジェクト型リテラルとインタフェースを使ったクラス定義」に手を加えてゆきます。このスーパークラス(Point)には、座標の原点からの距離とx座標正方向となす角度を返すメソッド(getLength()とgetAngle())があります。これらをつぎのようにgetアクセサで定めると、それぞれに与えた名前(lengthとangle)でプロパティと同じように参照できるようになります。getアクセサのメソッドに引数はなく、値を返さなければなりません。


class Point implements IPoint {

	// getLength(): number {
	get length(): number {
		var square: number = this.x * this.x + this.y * this.y;
		return Math.sqrt(square);
	}
	// getAngle(): number {
	get angle(): number {
		return Math.atan2(this.y, this.x);
	}

}

getアクセサは値を返すメソッドとして定め、つぎのようにプロパティのかたちで値が得られます。けれど、設定はできません。つまり、読み取り専用プロパティとして使えます。ただし、設定しても値が変えられないだけで、ビルドでエラーは起こりません。


var obj: Vector = Vector.polar(1, Math.PI / 3);
console.log(obj.length, obj.angle * Point.RAD_TO_DEG);  // 1 59.99999999999999

距離も角度も、クラス(Point)にはそれにあたるプロパティはなく、座標からそれぞれの値を求めて返しているだけです。getアクセサが仮想的なプロパティをつくったことになります。

02 setアクセサを使う

setアクセさを使えば、値ひとつを設定するメソッドがプロパティのかたちで呼び出せるようになります。前掲ふたつのgetアクセサの定めにsetも加えて、読み書きできるプロパティにしてみましょう。クラス(Point)が実際にもっているプロパティは座標(xとy)ですから、距離と角度から座標を求めなければなりません。幸いなことに、そのための静的なメソッド(getPolar())はすでに備わっています。

setアクセサのメソッドは、つぎのように引数をひとつだけとり、戻り値はありません。距離と角度のうちひとつは引数値に改め、もうひとつはgetアクセサの値を得て、静的メソッドに渡せば新たな座標(point)が求まります。そして、xy座標値をそれぞれのプロパティ(xとy)に定めればよいでしょう。


class Point implements IPoint {

	set length(length: number) {
		var point: IPoint = Point.getPolar(length, this.angle);
		this.x = point.x;
		this.y = point.y;
	}

	set angle(angle: number) {
		var point: IPoint = Point.getPolar(this.length, angle);
		this.x = point.x;
		this.y = point.y;
	}

}

これで、get/setアクセサにより、クラス(Point)に読み書きできる距離(length)と角度(angle)がプロパティのかたちで加えられました。つぎのように、値の設定および参照ができます。書き上げたTypeScriptコードは以下にまとめました(コード001)。なお、以下にサンプル001としてCodePenに書いたコードを掲げてあります。


var obj: Vector = Vector.polar(1, Math.PI / 3);
obj.length = 2;
obj.angle = Math.PI / 6;
console.log(obj.length, obj.angle * Point.RAD_TO_DEG);  // 2 29.999999999999996

コード001■get/setアクセサを定めたクラス


class Point implements IPoint {
	static RAD_TO_DEG: number = 180 / Math.PI;
	constructor(public x: number, public y: number) {
	}
	get length(): number {
		var square: number = this.x * this.x + this.y * this.y;
		return Math.sqrt(square);
	}
	set length(length: number) {
		var point: IPoint = Point.getPolar(length, this.angle);
		this.x = point.x;
		this.y = point.y;
	}
	get angle(): number {
		return Math.atan2(this.y, this.x);
	}
	set angle(angle: number) {
		var point: IPoint = Point.getPolar(this.length, angle);
		this.x = point.x;
		this.y = point.y;
	}
	static polar(length: number, angle: number): Point {
		var point: IPoint = Point.getPolar(length, angle);
		return new Point(point.x, point.y);
	}
	protected static getPolar(length: number, angle: number): IPoint {
		var x: number = length * Math.cos(angle);
		var y: number = length * Math.sin(angle);
		return {x: x, y: y};
	}
}
class Vector extends Point {
	constructor(x: number, y: number) {
		super(x, y);
	}
	scale(scale): void {
		this.x *= scale;
		this.y *= scale;
	}
	add(point: IPoint): void {
		this.x += point.x;
		this.y += point.y;
	}
	static polar(length: number, angle: number): Vector {
		var point: IPoint = Point.getPolar(length, angle);
		return new Vector(point.x, point.y);
	}
}
interface IPoint {
	x: number;
	y: number;
}

サンプル001■TypeScript: get / set accessors

See the Pen TypeScript: get / set accessors by Fumio Nonaka (@FumioNonaka) on CodePen.


作成者: 野中文雄
更新日: 2016年9月23日 TypeScriptのバージョンを2.0.3に更新。
作成日: 2016年9月14日


Copyright © 2001-2017 Fumio Nonaka.  All rights reserved.