aboutsummaryrefslogtreecommitdiff
path: root/files/ja/mozilla/tech/xpcom/language_bindings/components.constructor/index.html
blob: dba394eb69c203716a0b9e9b9d8ef752f50ef945 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
---
title: Components.Constructor
slug: Mozilla/Tech/XPCOM/Language_Bindings/Components.Constructor
tags:
  - 'XPCOM:Language Bindings'
  - XPConnect
translation_of: Mozilla/Tech/XPCOM/Language_Bindings/Components.Constructor
---
<p>
</p><p><span id="Summary"></span>
</p>
<h3 id="概要"> 概要 </h3>
<p>XPCOM コンポーネントの新規インスタンスを作成/生成するのに使用できる JavaScript 関数を作成します。
</p><p><span id="Syntax"></span>
</p>
<h3 id="構文"> 構文 </h3>
<pre class="eval">var func = [ new ] Components.Constructor(<i>contractID</i> [, <i>interfaceName</i> [, <i>initializer</i> ] ]);
</pre>
<p><span id="Parameters"></span>
</p>
<h3 id="パラメータ"> パラメータ </h3>
<dl><dt> <code>contractID</code></dt><dd> コンポーネントのコントラクト ID を含む文字列
</dd><dt> <code>interfaceName</code> </dt><dd> 与えられると、新規作成されるインスタンスそれぞれに対してこの文字列の名前のインターフェイスで <a href="ja/NsISupports/QueryInterface">QueryInterface</a> が呼び出される
</dd><dt> <code>initializer</code> </dt><dd> 与えられると、この文字列の名前の関数が、新規作成されるインスタンスに対してその時に与えられる引数を使って呼び出される
</dd></dl>
<p><span id="Description"></span>
</p>
<h3 id="説明"> 説明 </h3>
<p><code>Components.Constructor()</code> は XPCOM コンポーネントのインスタンス作成に便利なショートカットです。これを使うと、インスタンスを作りたい時に毎回 <code>Components.classes</code><code>Components.interfaces</code><code>createInstance</code> などをタイピングする手間が無くなります。また、より <a href="ja/JavaScript">JavaScript</a> 的な構文で XPCOM オブジェクトを作成できるようになります。もう一つの重要な恩恵として、<code>Components.Constructor()</code> はいくつかの計算をあらかじめ行うので、<code>Components.Constructor()</code> から返される関数を使って XPCOM オブジェクトを作成した方が下記に示すように基本原則に基づいてオブジェクトを作成するよりも高速になります。 (JavaScript エンジンと XPCOM の間のレイヤーをまたぐ回数がより少なくて済むというのも高速になる理由の一つです。)
</p><p><code>Components.Constructor()</code> によって返される関数のふるまいは、 <code>Components.Constructor()</code> が呼び出されたときに与えられた引数によって異なります。与えられた引数が 1 つだけなら、その引数は作成される XPCOM コンポーネントの<a href="ja/Contract_ID">コントラクト ID</a> になります。コンポーネントはすぐ返されますが、そのコンポーネントからは基本インターフェイスの <code><a href="ja/NsISupports">nsISupports</a></code> しか利用できません。なのでそのオブジェクトのメソッドを呼び出すためにはそれに対して <a href="ja/NsISupports/QueryInterface">QueryInterface</a> を呼び出さなければなりません。例えば、
</p>
<pre class="eval">var BinaryInputStream = Components.Constructor("@mozilla.org/binaryinputstream;1");
var bis = new BinaryInputStream();
print(bis.toString()); // "[xpconnect wrapped nsISupports]"

try
{
  // someInputStream は既存の nsIInputStream
  // bis は nsIBinaryInputStream に QI されていないのでエラーを投げる
  bis.setInputStream(someInputStream);
}
catch (e)
{
  bis.QueryInterface(Components.interfaces.nsIBinaryInputStream);
  bis.setInputStream(someInputStream); // これで成功
}
</pre>
<p>引数が 2 つ与えられると、作成されるインスタンスは第 2 引数の名前を持つ XPCOM インターフェイスに <code><a href="ja/NsISupports/QueryInterface">QueryInterface</a></code> されます。
</p>
<pre class="eval">var BinaryInputStream = Components.Constructor("@mozilla.org/binaryinputstream;1",
                                               "nsIBinaryInputStream");
var bis = new BinaryInputStream();
print(bis.toString()); // "[xpconnect wrapped nsIBinaryInputStream]"

// someInputStream は既存の nsIInputStream
bis.setInputStream(someInputStream); // 成功
</pre>
<p>引数が 3 つ与えられると、インスタンスに対して <code><a href="ja/NsISupports/QueryInterface">QueryInterface</a></code> されるだけでなく、初期化メソッドも呼び出されたことになります。初期化メソッドに使われる引数は、<code>Components.Constructor()</code> によって作成された関数を呼び出す時に渡された引数です。
</p>
<pre class="eval">var BinaryInputStream = Components.Constructor("@mozilla.org/binaryinputstream;1",
                                               "nsIBinaryInputStream",
                                               "setInputStream");
try
{
  // 引数の数が nsIBinaryInputStream.setInputStream が
  // 取るものと異なるのでエラーを投げる
  var bis = new BinaryInputStream();
}
catch (e)
{
  // someInputStream は既存の nsIInputStream
  bis = new BinaryInputStream(someInputStream); // 成功
  var bytes = bis.readByteArray(<i>someNumberOfBytes</i>); // 成功
}
</pre>
<p>基本原則に基づいたインスタンスの作成と <code>Components.Constructor()</code> を使ったインスタンスの作成を比較して下さい。後者の方が前者よりもずっと (たくさんの違う場所でコンポーネントのインスタンスを作成している場合には特に) 読みやすくなります。
</p>
<pre class="eval">var bis = Components.classes["@mozilla.org/binaryinputstream;1"]
                    .createInstance(Components.interfaces.nsIBinaryInputStream);
bis.setInputStream(someInputStream);
</pre>
<pre class="eval">// 前もって BinaryInputStream が初期化されているとして
var bis = new BinaryInputStream(someInputStream);
</pre>
<p><code>Components.Constructor()</code> は、他の一般的なメソッドを使って実現できる挙動のシンタックスシュガーに過ぎません (高速できれいなシンタックスシュガーですが)。 次の JavaScript 関数と等価です。
</p>
<pre class="eval">function Components_Constructor(contractID, interfaceName, initializer)
{
  var ccArgs = arguments;

  function ctor()
  {
    var instance = Components.classes[contractID]
                             .createInstance(Components.interfaces.nsISupports);

    if (ccArgs.length &gt; 1)
    {
      instance.QueryInterface(Components.interfaces[interfaceName]);

      if (ccArgs.length &gt; 2)
        instance[initializer].apply(instance, arguments);
    }

    return instance;
  }

  return ctor;
}
</pre>