この記事のURL

http://www.dango-itimi.com/blog/archives/2014/001209.html


FLASH tips Haxe ジェネリック関数 Generic functions を使ってみた

Haxe のジェネリック関数というものを利用してみました。利用してみたのは初めてに近いので、使用方法が誤っていたり もしくはもっと良い利用方法があるかもしれません。

まず以下の様な Polygon クラスがあるとします。

#if js
import createjs.easeljs.Point;
#else
import flash.geom.Point;
#end

class Polygon {

	private var vertices:Array<Point>;

	public function new(){

		vertices = [
			new Point(0, 0),
			new Point(10, 0),
			new Point(10, 10),
			new Point(0, 10)
		];
	}
}

Polygon クラス内には、頂点座標 Point クラスの配列 vertices があります。Point クラスは、AS3 あるいは CreateJS のクラスです。

ここで、物理演算ライブラリ Box2D や Nape から上記 Polygon.vertices の座標情報を利用したい場合、Point クラスを B2Vec2 クラス(Box2D)、あるいは Vec2 クラス(Nape)に変換する必要が出てきます。

まずは深く考えず、以下の様なメソッドを Polygon クラス内に設けるとします。

	public function convertVerticesToB2Vec2():Array<B2Vec2>{

		return [
			for(vertex in vertices) new B2Vec2(vertex.x, vertex.y)
		];
	}
	public function convertVerticesToVec2():Array<Vec2>{

		return [
			for(vertex in vertices) new Vec2(vertex.x, vertex.y)
		];
	}

上記二つのメソッドの難点としましては、Polygon クラス内に Box2D と Nape の専用のクラスが記述されてしまっているという点にあります。例えば Box2D のみ利用したいのに Nape のクラスファイルもインポートしなくてはならない、という事態が発生してしまいます。

この問題を解決するために、convertVerticesToB2Vec2 と convertVerticesToVec2 は削除し、以下の様なメソッドに変更します。

	public function convertVertices<T>(convertedClass:Class<T>):Array<T>{

		return [
			for(vertex in vertices) Type.createInstance(convertedClass, [vertex.x, vertex.y])
		];
	}

これにより以下のように利用できます。

var polygon = new Polygon();
var vertices = polygon.convertVertices(B2Vec2); //Box2D
//var vertices = polygon.convertVertices(Vec2); //Nape

Polygon クラスを利用する側で、Box2D あるいは Nape といったライブラリのインポートを選択できるようになります。

しかして上記 convertVertices メソッドは、Array や String クラスを指定する事もできてしまいます。Int を指定するとコンパイルエラーになります。

var polygon = new Polygon();
polygon.convertVertices(Array); //ok
polygon.convertVertices(String); //ok
polygon.convertVertices(Int); //error

本来は String クラスのコンストラクタ第二引数は指定できませんが、Type.createInstance 経由ですと指定可能となってしまうようです(第二引数は破棄されます)。

Type.createInstance 前にコンパイルエラーチェックはできないかと考えた所、以下の記述でいけました。


	@:generic public function convertVertices<T:{function new(x:Float, y:Float):Void;}>(convertedClass:Class<T>):Array<T>{

		return [
			for(vertex in vertices) Type.createInstance(convertedClass, [vertex.x, vertex.y])
		];
	}

これにより convertVertices には、「コンストラクタ引数に 二つの Float 型を指定するクラス」のみ指定が可能になります。(多分)

polygon.convertVertices(B2Vec2); //ok
polygon.convertVertices(Vec2); //ok
polygon.convertVertices(Array); //error
polygon.convertVertices(String); //error

@:generic 指定に関しましては以下のサイトの Generic functions の項で説明がありますが、難しい英単語が多くてよくわかっていません。

参考)Haxe 3 New Features
http://haxe.org/manual/haxe3/features

[ FLASH ] [ tips ] 投稿者 siratama : 2014年03月05日 19:36

トラックバック

http://www.dango-itimi.com/blog/mt-tb.cgi/1169

コメント

以下コメントを書き込むだけでは、管理人には通知が行われません。通知を行いたい場合、管理人の書き込みに「返信」を押してコメントをしていただくか、あるいは Google+, Twitter へご連絡ください。




[EDIT]