JavaScript で親クラスのコンストラクタを呼ばずに継承を行う

JavaScript の prototype を使った継承のオーソドックスな形は以下のような感じだと思います。

function SuperClass(name) {
	this.name = name;
}
SuperClass.prototype.hello = function() { alert(this.name+" : hello!"); }

function ChildClass() {
	SuperClass.call(this, "Koyomi Araragi");
}
ChildClass.prototype = new SuperClass("");

new ChildClass().hello();

親クラスのprototypeにアクセスするために、ChildClass.prototype に親クラスのインスタンスを生成して代入しています。これにより ChildClass のインスタンスから親クラスの hello が呼べるようになります。

この方法だと、継承のたびに親クラスのコンストラクタを呼ばなければなりません。親クラスのコンストラクタが、無効な引数に対して例外を投げる設計だったり、問題となる副作用を持っていたりすると厄介です。

以下のようにすると、親クラスのコンストラクタを呼ばずに継承を行えます。

function createObjectForPrototype(type) {
	var f = function(){};
	f.prototype = type.prototype;
	return new f();
}

function SuperClass(name) {
	this.name = name;
}
SuperClass.prototype.hello = function() { alert(this.name+" : hello!"); }

function ChildClass() {
	SuperClass.call(this, "Koyomi Araragi");
}
ChildClass.prototype = createObjectForPrototype(SuperClass);

new ChildClass().hello();

Gmail から Xperia へフリガナを同期する方法 改

自分の環境では上手くいきましたが、最悪データが壊れる恐れがあります。バックアップを忘れずに。自己責任で使用してください。

前記事で Gmail から Xperia へフリガナを同期する方法を書きました。Gmail からエクスポートした CSV を弄る際に

  1. 操作ミスで電話番号の先頭の 0 が消える
  2. メモなどに改行を含むデータを扱えない

という欠点がありました。
そこで CSV を扱う部分を自動化した ruby スクリプトを書きました。ruby が分からない人はゴメンなさい。

続きを読む

Gmail から Xperia へフリガナを同期する方法

Xperia の連絡帳を Gmail から同期するとフリガナが反映されないことがあります。正確には「Gmail の連絡帳にはフリガナが登録されているのに、Xperia では反映されない」という状況です。その対策方法です。

自分の環境では上手くいきましたが、最悪データが壊れる恐れがあります。自己責任でお願いします。
4/3 CSV の項目に改行が含まれていると、おかしくなるようです。内容が理解できる方以外は実行しないでください。

続きを読む

動画『midiで音声を表現するテスト』とボカロは比較にならない


midiで音声を表現するテスト」なる動画がニコニコのランキングに上がっていました.すごいですねこれ、びっくりです.
ところでこの動画のコメで「ボカロにくらべて自然!」というようなボカロとの比較コメが結構あるのですが、この動画の技術はボカロとは(おそらく)別物です.
ボカロは歌詞や音程やらを入力してやるとそこから音声を合成してくれる技術.
一方動画の技術は、元となる音声は(おそらく)存在していて、それをMIDIで再現する技術です.

ボカロの凄いところは、最初に用意された声優さんの声データを何とか切り貼りして、0からユーザーの思い通りの歌声が作れるところ.
動画技術の凄いところは、もともとある歌声をMIDIという限られた音色の中で再現できてしまうところ.

まぁ、動画の作者さんに聞いたわけではないので100%ではないですが、恐らくこんな感じじゃないかと思います.
だから、残念ながらこの動画の技術を直接ボカロに活用することはできないはずです.ボカロで生成した歌声をこの技術でMIDIで鳴らすなんてのはありかも.

XMLStore をコミットしたよ!

XML と ASObject の相互変換を行う XMLStore を Spark にコミットしました.
データ保存やサーバーとのやり取りで使えます.

var store:XMLStore = new XMLStore();
store.register(new PointXMLStorePart(), Point);
			
var point:Point = new Point(20, 30);
var xml:XML = store.toXML(point);

こんな書くと以下のようなXMLを生成できます.

<Point type="flash.geom.Point">
  <x type="Number">20</x>
  <y type="Number">30</y>
</Point>

独自のクラスを変換したいときは XMLStorePart のサブクラスを書いて XMLStore に register すれば OK!
一応ガワは出来上がっているので、あとは Rectangle とか Matrix とかよく使うオブジェクトの XMLStorePart を必要に応じて追加していこうと思います.

興味がある方は使ってみてくださいね!
http://www.libspark.org/wiki/hidachinoiro/XMLStore

新しい書き方

ECMAScript (JavaScript, ActionScript など) では new の対象に関数を持ってくることができる.

function foo() {}
new foo();

この関数をコンストラクタ関数とよび、ふつうはコンストラクタ関数内で this を使って生成されるオブジェクトにアクセスする.
ところがコンストラクタ関数内で新しくオブジェクトを作って返してやると、それが new で生成されるオブジェクトになるらしい.

function foo() {
    var a={};
    return a;
}

// ↓これで返ってくるのは a だよ!
new foo();

この a を関数とすることもできる.また、コンストラクタ関数内で a にプロパティを設定することもできる*1ので、

  1. ふつうにメソッドやプロパティを持つ
  2. しかも関数として呼べる

不思議なオブジェクトを new で生成することが可能だ.

function foo() {
    var a = function(){ return "test"; };
    a.say = function(){ return "hello"; };
    return a;
}

a.say() // hello
a();    // test

これをメソッドチェーンの形と混ぜてやると以下のような書き方が合法になる.

a = new foo(); // <-- 関数としても呼べるオブジェクト
a.foo(5)
 .bar(4)
 (2)
 .foo(5);

これでなにかおもしろいライブラリが作れないか考え中.

*1:ただし ActionScript の場合は変数の型宣言を * にするのを忘れずに