目次 | |

7. 特性

特性は,Java Beanの見かけ又は振舞いに影響を及ぼすことのできる, 名前の付いた離散的属性とする。 例えば,GUIボタンは,“Label”と名前を付けられた特性をもち, ボタン内で表示されたテキストを表す。

特性は,次のいくつかの方法で出現する。

a) 特性は,スクリプトの環境で,オブジェクトのフィールドと同様なものとして, 現れる可能性がある。そのため,Javaスクリプト環境では,“b.Label = foo”を実行し, 特性の値を設定することがある。
b) 特性は,他の部品が,その取得メソッド及び設定メソッドを呼び出すことによって, プログラムとしてアクセスできる(7.1参照)。
c) 部品をカスタム化する(9.参照)プロセスの一部として,その特性を, ユーザが編集する特性シート内で示してもよい。
d) 典型的に,ビーンの特性は永続的とし,そのために, 特性の状態は,ビーンの永続的状態の一部として保存される。

特性は,任意の型を所有できる。任意の型は,“int”などの組込みJava型及び “java.awt.Color”などのクラス又はインタフェース型を含む。

7.1 アクセサメソッド

特性は,常に,その特性を所有するオブジェクトにおけるメソッド呼出しで, アクセスする。読取り可能な特性には,特性を読み取る取得メソッド getter が存在し,書込み可能な特性には,特性の値を更新できる設定メソッド setter が存在する。そこで,スクリプト記述者が,“b.Label = foo” などを入力する場合であっても, 特性を設定するための対象オブジェクトへのメソッドの呼出しは存在し, 対象オブジェクトは,完全なプログラム的制御をもつ。

そのため,特性は,単純なデータフィールドの必要はない。 実際,計算された値とすることもできる。 更新には,様々のプログラム的な副作用が存在してもよい。 例えば,ビーンの背景色の特性を変更した場合,ビーンも新しい色で塗り直されてもよい。

単純な特性に対する,アクセサの型シグネチャは,次による。

	void setFoo(PropertyType value); // simple setter 
	PropertyType getFoo();           // simple getter

GetFoo及びSetFooは,単に例としての名前とする。 アクセサメソッドは,任意の名前を所有できる。 ただし,アクセサメソッド用の標準命名規約については,8.3に示す設計パタンを参照のこと。

7.2 インデクス付き特性

単純な単値特性に加え,インデクス付き特性(indexed propoerty) もサポートする。 インデクス付き特性は,値の範囲をサポートする。 インデクス付き特性を読み取る又は書き込む場合はいつも,インデクスを指定して, 必要な値を識別する。

特性のインデクスは,Javaの“int”でなければならない。

将来的にこの制限は緩和され,他のインデクス型が許可される可能性がある。 しかし“int”のインデクスは,特性インデクスの種類中,事実上, 最も共通的及び有用なものとなる。

部品も,単一の配列値として,インデクス付き特性を開示する可能性がある。 例えば,文字列型の“fred”というインデクス付き特性があれば,スクリプト環境から, “b.fred[3]”を使って,個々のインデクス付き値にアクセス可能とする。 “b.fred”を使った配列としても,同じ特性にアクセスできる。

インデクス付き特性に対応する,アクセサの型シグネチャは,次による。

	void setter(int index, PropertyType value); // indexed setter 
	PropertyType getter(int index);             // indexed getter 
	void setter(PropertyType values[]);         // array setter 
	PropertyType[] getter();                    // array getter

インデクス付き取得メソッド及びインデクス付き設定メソッドは, 現配列の限界の外部でインデクスを使用した場合, java.lang.ArrayIndexOutofBoundsException という実行時例外を投げる可能性がある。

配列の大きさを変更するためには,配列設定メソッドを使用して, 新しい(又は更新された)配列を設定しなければならない。

7.3 アクセサメソッドの例外

単純な特性アクセサメソッド又はインデクス付き特性アクセサメソッドは, いずれも検査済み例外を投げる可能性がある。 これによって,特性設定メソッド及び特性取得メソッドは, 例外状況を報告することが可能になる。

そこで,例えば,次のとおりにプログラムできる。

	void setWombat(Wombat value) throws BadWombatException; 
	Marsupial getKangaroo(int index) throws AwfulCommunicationException;

7.4 束縛特性及び制約付き特性

Java Beansは,束縛特性(bound property) 及び 制約付き特性(constrained property) のサポートを提供する。 これらは,単純なビーンズ又は初期のビーンズプログラムには必要とされない, 上級用の特徴とする。

7.4.1 束縛特性

ビーン特性が変更される場合,ビーンのコンテナ又は他のビーンのいずれかが, その変更の通知を望むことがある。

部品は,その特性のいくつか又はすべてに対応した, 変更通知サービスの提供を選択できる。 これらの特性は,一般に 束縛特性(bound property) として知られている。 これは,これらの特性によって,他の部品が, 特定の振舞いを特性の変更と結合できることによる。

PropertyChangeListener というイベントリスナインタフェースは, 単純な束縛特性への更新を報告するために使用する。 ビーンが束縛特性をサポートすれば,次に示すPropertyChangeListenerに対応する, 通常の一対のマルチキャストイベントリスナ登録メソッドをサポートすることが望ましい。

	public void addPropertyChangeListener(PropertyChangeListener x); 
	public void removePropertyChangeListener(PropertyChangeListener x);

特性変更が束縛特性で発生する場合,ビーンは,登録済みのあらゆるリスナで, メソッドPropertyChangeListener.propertyChangeを呼び出し, ロケール非依存の特性の名前並びにその旧値及び新値をカプセル化する PropertyChangeEvent オブジェクトを渡すことが望ましい。

イベントソースは,その内部状態を更新した で, イベントを起動するのがよい。

プログラムを簡便にするため,ユティリティクラスPropertyChangeSupportを提供する。 これは,PropertyChangeListenerを保持し, イベントPropertyChangeを起動するために使用できる。

7.4.2 制約付き特性

特性の変更が発生した場合,他のビーンが,変更を検査し, その変更が不適切なときには,それを拒否したいことがある。

この種の検査を受ける特性を,制約付き特性(constrained property) と呼ぶ。

Java Beansでは,制約付き特性設定メソッドは,PropertyVetoException をサポートするために必要とする。このメソッドは,制約付き特性のユーザに, 試みた更新を拒否するかもしれないことを文書化して通知する。

そのため,単純な制約付き特性は,次の例と同様に見えるかもしれない。

	PropertyType getFoo();
	void setFoo(PropertyType value) throws PropertyVetoException;

VetoableChangeListener イベントリスナインタフェースは, 制約付き特性へ更新を報告するために使用する。 ビーンが制約付き特性をサポートすれば,ビーンは次の例のとおり、 VetoableChangeListenerに対応する,マルチキャストイベントリスナ登録メソッドの 通常の対をサポートしなければならない。

	public void addVetoableChangeListener(VetoableChangeListener x); 
	public void removeVetoableChangeListener(VetoableChangeListener x);

制約付き特性において,特性の変更が発生すると, ビーンは,登録済みのあらゆるリスナにおけるメソッド VetoableChangeListener.vetoableChange を呼び出し, ロケール非依存の特性の名前並びにその旧値及び新値をカプセル化するオブジェクト PropertyChangeEvent を渡すことが望ましい。 イベントの受信者が,要求のとおりの編集を実行させたくない場合は, PropertyVetoExceptionを投げるかもしれない。 この例外を捕捉し,旧値に戻し,新しい VetoableChangeListener.vetoableChange イベントを起動し,旧値に戻ったことを報告するのは,ソースのビーンの責任とする。

最初の vetoableChangeListener.vetoablePropertyChange イベントは, 受信者の一つが新値を拒否する前に,多くの受信者に対しマルチキャストされたかもしれない。 受信者の一つが拒否する場合,他のすべての受信者に, 旧値に戻ったことを確実に通知しなければならない。 そこで,旧値に戻す場合には,別のイベント VetoableChangeListener.vetoableChange を起動する必要がある。 ソースは,旧値に戻す場合,拒否を無視する選択をしてもよい。

イベントソースは,その初期状態を更新する に, イベントを起動させるのがよい。

プログラムを簡素化するために,ユティリティクラス VetoableChangeSupport を提供する。これは,VetoableChangeListeners を保持し, イベント VetoableChange を起動するために使用できる。 PropertyVetoException を捕捉し,必要な戻しイベントを送ることも行う。

7.4.3 束縛及び制約付き特性のリスニング

一般に,特性を制約する場合は,束縛もするほうがよい。 他のビーンズに特性に対する変更の拒否を許すことが望ましければ,普通は, 特性が実際に変更されたときに,それらのビーンズに通知可能とすることも 望ましい。

ビーンが,一つの束縛及び制約付き特性をサポートすれば, 特性の更新前に,イベント VetoableChangeListener.vetoableChange を起動し, 特性の更新後に,イベント PropertyChangeListener.propertyChange を起動するのがよい。

そこで,ビーンが,提案される更新を拒否すること, 及び特性の状態を正確にモニタすることの両方に関心があれば, そのビーンは,“二段階”の手法を取り,VetoableChangeListener 及び PropertyChangeListener の両方を登録することが望ましい。 vetoableChange における最初の段階では,単に,提案された値が受諾可能かどうか, 及び拒否を受け入れる可能性がある値かどうかを検査するのがよい。 PropoertyChange における2番目の段階では,変更が有効となることに依存可能で, 新しい値で動作することを開始できる。

経験のある開発者の中には,特性の状態を追跡するために,“一段階”の機構を使用し, VetoableChangeListener だけを登録し,継続する vetoableChange 通知を通じて, ビーンの状態を追跡することを選択するかもしれない。結局のところ,続いて vetoableChange が拒否されれば,新しい vetoableChange が, 旧値に戻されたことを通知するために送られる。しかし,この手法は, 新しい値が本当に有効となるときを確実にすることが困難なので,元来, 微妙な手法である。この手法は,安全に使用するには,かなりの注意が要求される。 しかし,ある状況では,この手法が適切なこともあるかもしれない。

7.4.4  影響を及ぼさない変更に関する検査

特性設定メソッドが,特性の現在値と等しい実引数で呼び出さる場合は, ビーンが,イベント VetoableChangeListener.vetoableChange もイベント PropertyChangeListener.propertyChange も起動しないことが望ましい。 この振舞いは,特性設定メソッドが,相互に接続している場合に, より効率的となり,ループの危険性も軽減する。

そこで,例えば,束縛特性“fred”における次の特性の更新は, PropertyChangeEvent の起動を必要としない。

	x.setFred(x.getFred());

ユティリティクラス PropertyChangeSupport 及び VetoableChangeSupport を使用するコードに対しては,等価性に対するこの検査は,自動的に処理される。 これは,これらのクラスが,旧特性値及び新特性値が等しくいかどうかを検査し, 等しければ,イベントの起動を回避することによる。

7.4.5 名前付き特性のリスニングに対するオプションのサポート

7.4.1で示す PropertyChangeListeners の追加及び削除に対する標準設計パタンを サポートすることに加えて,PropertyChangeEventsを起動するビーンは, 名前付き特性に対して PropertyChangeListener を追加及び削除できるメソッドの 付加的な対もサポートしてよい。この対は,次による。

	void addPropertyChangeListener(String propertyName,
				PropertyChangeListener listener);
	void removePropertyChangeListener(String propertyName,
				PropertyChangeListener listener);

この場合,ビーンは,与えられたリスナを与えられた特性名と関連付け, 与えられた名前付き特性が変更された場合には,メソッド propertyChange だけを起動することが望ましい。

同様に,VetoableChangeListeners の追加用及び削除用の標準設計パタンをサポートすることに加えて,ビーンズは, 特定の名前付き特性と結びついた付加的な登録メソッドもサポートしてよい。 この登録メソッドは,次による。

	void addVetoableChangeListener(String propertyName,
				VetoableChangeListener listener);
	void removeVetoableChangeListener(String propertyName,
				VetoableChangeListener listener);

いずれの場合も,ビーンは,一つのイベントリスナ引数を取る, イベントリスナ登録用の標準設計パタンも, サポートしなければならないことに注意すること。

7.4.6 特定の特性に対するオプションのイベントハンドラメソッド

7.4.5で示した機構の代わりに,ビーンは, 特定の特性に対するイベントハンドラの登録及び削除を可能とする, 明示的なメソッドを提供してもよい。これは,完全にオプションとする。 しかし,ビーンが,これをサポートする場合は,その各束縛特性に対して, 次の形式のメソッドを提供してもよい。

	void add<PropertyName>Listener(PropertyChangeListener p);
	void remove<PropertyName>Listener(PropertyChangeListener p);

さらに,VetoableChangeListener の登録及び削除に対する, オプションの同様な名前付きメソッドの対を付加してもよい。

	void add<PropertyName>Listener(VetoableChangeListener p);
	void remove<PropertyName>Listener(VetoableChangeListener p);

7.4.7 束縛及び制約の例

次に挙げた例では,クラス JellyBean は,束縛特性“color”並びに束縛及び制約付き特性 “priceInCents”をサポートする。イベントリスナを保持し,実際のイベントを配布するために, クラス PropertyChangeSupport 及びクラス VetoableChangeSupport のインスタンスを使用する。

	import java.awt.*; 
	import java.beans.*; 

	public class JellyBean {{ 

	    public Color getColor() { { 
	        return ourColor; 
	    } 

	    public void setColor(Color newColor) {{ 
	        Color oldColor = ourColor; 
	        ourColor = newColor; 
	        changes.firePropertyChange("color", oldColor, newColor); 
	    } 

	    public int getPriceInCents() { { 
	        return ourPriceInCents; 
	    } 

	    public void setPriceInCents(int newPriceInCents) 
				        throws PropertyVetoException { { 
	        int oldPriceInCents = ourPriceInCents; 
	        // First tell the vetoers about the change. If anyone objects, we 
	        // let the PropertyVetoException propagate back to our caller. 
	        vetos.fireVetoableChange("priceInCents", 
	                                 new Integer(oldPriceInCents), 
	                                 new Integer(newPriceInCents)); 
	        // No one vetoed, so go ahead and make the change. 
	        ourPriceInCents = newPriceInCents; 
	        changes.firePropertyChange("priceInCents", 
	                                   new Integer(oldPriceInCents), 
	                                   new Integer(newPriceInCents)); 
	    } 

	    public void addPropertyChangeListener(PropertyChangeListener l) { { 
	        changes.addPropertyChangeListener(l); 
	    } 

	    public void removePropertyChangeListener(PropertyChangeListener l) { { 
	        changes.removePropertyChangeListener(l); 
	    } 

	    public void addVetoableChangeListener(VetoableChangeListener l) { { 
	        vetos.addVetoableChangeListener(l); 
	    } 

	    public void removeVetoableChangeListener(VetoableChangeListener l) { { 
	        vetos.removeVetoableChangeListener(l); 
	    } 

	    private PropertyChangeSupport changes = 
			        new PropertyChangeSupport(this); 
	    private VetoableChangeSupport vetos = new VetoableChangeSupport(this); 
	    private Color ourColor = Color.orange; 
	    private int ourPriceInCents = 2; 
	}

7.5 特性関連 API

7.5.1 クラス PropertyChangeEvent

public class java.beans.PropertyChangeEvent 
    extends java.util.EventObject

ビーンが,“束縛”特性又は“制約付き”特性を変える場合はいつでも, イベント“PropertyChange”を配布する。 オブジェクト PropertyChangeEvent は,メソッド PropertyChangeListener 及びメソッド VetoableChangeListener に実引数として送出する。

通常,PropertyChangeEvent は,変更された特性の名前及び新旧の値に付随する。 新値が,組込み型(int,booleanなど)の場合,対応する java.lang.Object 型 (Integer,Booleanなど)としてラップされなければならない。

null値は,その本当の値が未知の場合,新旧の値として提供してよい。

イベントソースは,名前として“null”オブジェクトを送出し, その特性が変わったかどうかの任意の集合を示す可能性がある。 この場合,新旧の値も null であることが望ましい。

a) コンストラクタ

b) メソッド

7.5.2 インタフェースPropertyChangeListener

public interface java.beans.PropertyChangeListener 
    extends java.util.EventListener
ビーンが“束縛”特性を変更する場合は,必ずイベント“PropertyChange”を起動する。 ソースビーンで,PropertyChangeListener を登録し, すべての束縛特性の更新を通知させることができる。

a) メソッド

7.5.3 クラスPropertyChangeSupport

public class java.beans.PropertyChangeSupport 
    extends java.lang.Object 
    implements java.io.Serializable
これは,ユティリティクラスで,束縛特性をサポートするビーンによって使用できる。 ビーンのメンバフィールドとしてこのクラスのインスタンスを使用し, それに様々な作業を委譲できる。

a) コンストラクタ

b) メソッド

7.5.4 クラス ProertyVetoException

public class java.beans.PropertyVetoException 
    extends java.lang.Exception
特性に提示された変更が受け入れ不可能な値を表す場合, PropertyVetoExceptionが投げられる。

a) コンストラクタ

b) メソッド

7.5.5 インタフェースVetoableChangeListener

public interface java.beans.VetoableChangeListener 
    extends java.util.EventListener
ビーンが“制約付き”特性を変更する場合は,必ずイベントVetoableChangeが起動する。 ソースビーンでVetoableChangeListenerを登録し, すべての制約付き特性の更新を通知させることができる。

a) メソッド

7.5.6 クラスVetoableChangeSupport

public class java.beans.VetoableChangeSupport 
    extends java.lang.Object 
    implements java.io.Serializable
これは,ユティリティクラスで, 制約付き特性をサポートするビーンによって使用できる。 ビーンのメンバフィールドとしてこのクラスのインスタンスを使用し, それに様々な作業を委託できる。

a) コンストラクタ

b) メソッド



目次 | |