HTML5テクニカルノート
TypeScript入門 06: メソッド引数のデフォルト値と省略および定数を定める
- ID: FN1609007
- Technique: HTML5 / JavaScript
- Package: TypeScript 2.0.3
TypeScriptでは、メソッドの引数にデフォルト値を与えたり、引数を省略することもできます。また、値の変えられない定数の定め方についてもご説明します。
01 メソッドの引数にデフォルト値を与える
本稿は、「TypeScript入門 05: get/setアクセサをを使う」で書いたコード001「get/setアクセサを定めたクラス」に手を加えてゆきます。このスーパークラス(Point)のコンストラクタには、座標値をふたつの引数として与えます。引数を渡さずに呼び出せば、引数の数が合わないというつぎのようなエラーが示されます。
Supplied parameters do not match any signature of call target.
けれど、引数なしに呼び出したとき、たとえばデフォルト値として0を与えることができると便利です。メソッドや関数の引数には、つぎのように=
演算子でデフォルト値が定められます。引数を受け取ればその値、引数がないときはデフォルト値が使われることになります。サブクラス(Vector)のコンストラクタもスーパークラス(Point)と同じ引数をとりますので、デフォルト値を加えました。
class Point implements IPoint { constructor(public x: number = 0, public y: number = 0) { } } class Vector extends Point { constructor(x: number = 0, y: number = 0) { super(x, y); } }
これで、コンストラクタを引数なしに呼び出したときは、つぎのようにデフォルト値がプロパティに与えられます。
var obj: Vector = new Vector(); console.log(obj.x, obj.y); // 0 0 obj.length = 2; obj.angle = Math.PI / 6; console.log(obj.length, obj.angle * Point.RAD_TO_DEG); // 2 29.999999999999996
02 メソッドの引数が省かれたときの処理を定める
サブクラス(Vector)には。座標に定数値を乗じて伸縮させるメソッド(scale())が備わっています。この乗数の引数として、xyそれぞれ別の値が渡せるように書き替えてみました。
class Vector extends Point { // scale(scale): void { scale(scaleX: number, scaleY: number): void { this.x *= scaleX; // scale; this.y *= scaleY; // scale; } }
メソッド(scale())に渡したふたつの引数は、つぎのようにxy座標それぞれに乗じられます。
var obj: Vector = new Vector(1, 1); obj.scale(1, Math.sqrt(3)); console.log(obj.length, obj.angle * Point.RAD_TO_DEG); // 1.9999999999999998 59.99999999999999
もっとも、もとのメソッドと同じように引数ひとつでも使えると便利です。その場合、xyそれぞれに同じ引数値を乗じます。けれど、引数の数が合わないと、つぎのようにエラーが起こります。
Supplied parameters do not match any signature of call target.
引数の後につぎのように?
記号を添えると、その引数は省けるようになります。そのうえで、第2引数が渡されないときは、替わりに第1引数の値を用いればよいのです。
class Vector extends Point { scale(scaleX: number, scaleY?: number): void { this.x *= scaleX; this.y *= (isNaN(scaleY) ? scaleX : scaleY); // scaleY; } }
これで、メソッドに引数をひとつだけ渡して呼び出したとき、xy座標に同じ引数値が乗じられます。
var obj: Vector = Vector.polar(1, Math.PI / 3); obj.scale(2); console.log(obj.length, obj.angle * Point.RAD_TO_DEG); // 2 59.99999999999999
03 定数を定める
スーパークラス(Point)には、静的プロパティ(RAD_TO_DEG)としてラジアンから度数への変換比率が納められています。この値はつねに変わりません。けれど、public
のプロパティですので、つぎのように書き替えができてしまいます。
var obj: Vector = Vector.polar(1, Math.PI / 3); Point.RAD_TO_DEG = 0; console.log(obj.length, obj.angle * Point.RAD_TO_DEG); // 1 0
TypeScriptはキーワードconst
で、以下のように定数が宣言できます。この値を書き替えようとすると、つぎのようにそれはできないというエラーが示されます。
Left-hand side of assignment expression cannot be a constant.
const RAD_TO_DEG: number = 180 / Math.PI; var obj: Vector = Vector.polar(1, Math.PI / 3); RAD_TO_DEG = 0; console.log(obj.length, obj.angle * Point.RAD_TO_DEG);
ただし、クラスのプロパティにconst
宣言は使えません。つぎのようにエラーが出てしまいます。
A class member cannot have the 'const' keyword.
でも、書き替えできないプロパティは定められます。つぎのように、get
アクセサを用いればよいのです。set
アクセサがないかぎり、この値は変えられません。ただし、書き替えようとしても、ビルドでエラーは起こらないことにお気をつけください。
class Point implements IPoint { // static RAD_TO_DEG: number = 180 / Math.PI; static get RAD_TO_DEG(): number { return 180 / Math.PI; } }
var obj: Vector = Vector.polar(1, Math.PI / 3); Point.RAD_TO_DEG = 0; console.log(obj.length, obj.angle * Point.RAD_TO_DEG); // 1 59.99999999999999
TypeScriptコードをまとめるとつぎのとおりです(コード001)。また、以下にサンプル001としてCodePenに書いたコードを掲げてあります。
コード001■メソッド引数にデフォルト値と省略時の処理および定数を定める
class Point implements IPoint {
constructor(public x: number = 0, public y: number = 0) {
}
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 get RAD_TO_DEG(): number {
return 180 / Math.PI;
}
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 = 0, y: number = 0) {
super(x, y);
}
scale(scaleX: number, scaleY?: number): void {
this.x *= scaleX;
this.y *= (isNaN(scaleY) ? scaleX : scaleY);
}
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: Default and optional parameters and a read-only property
See the Pen TypeScript: Default and optional parameters and a read-only property by Fumio Nonaka (@FumioNonaka) on CodePen.
- TypeScript: とにかくJavaScriptファイルをビルドしてみる
- TypeScript入門 01: Visual Studio CodeでTypeScriptのコードを書く
- TypeScript入門 02: publicとprivateおよびstatic
- TypeScript入門 03: クラスを継承して使う
- TypeScript入門 04: オブジェクト型リテラルとインタフェースを使う
- TypeScript入門 05: get/setアクセサをを使う
- TypeScript入門 07: ブロックスコープに変数を宣言する ー let
- TypeScript入門 08: 型の互換性
- TypeScript入門 09: アロー関数式
- TypeScript入門 10: モジュール ー exportとimport
- TypeScript入門 11: 名前空間 ー namespace
- TypeScript入門 12: デコレータ(Decorator)を使う
作成者: 野中文雄
更新日: 2016年9月23日 TypeScriptのバージョンを2.0.3に更新。
作成日: 2016年9月14日
Copyright © 2001-2017 Fumio Nonaka. All rights reserved.