私は、accessorを紹介した「accessorを使用するとJavaコードの堅牢性が高まります」の中で、accessor (フィールドの値を直接操作するメンバー関数) がコードに最小限のオーバーヘッドを与える可能性があることを述べました。しかし同時に、accessorは、クラスのインプリメンテーションの詳細を隠すのに役立ちますので、クラスおよびコンポーネントの堅牢性を高めます。accessorにはsetterとgetterの2つのフレーバーがあります。setterはフィールドの値を変更し、getterはフィールドの値を取得します。
あるメンバー関数のvisibilityを選択すると、Javaオブジェクトによるその関数へのアクセス・レベルが定義され、ユーザーのソフトウェア内の結合を減らすことが可能になります。accessorは単なるJavaメンバー関数であるため、accessorのvisibilityを慎重に選択することが大切です。"Java プログラムにおけるメンバー関数の visibility" の中で述べたように、Javaでは、public、protected、private、およびデフォルトの4つのレベルのvisibilityが使用できます。
- public visibilityが指定されたメンバー関数は、他のどのオブジェクトまたはクラスの中の、どの任意のメンバー関数によっても呼び出すことができます。
- protected visibilityが指定されたメンバー関数は、その関数を定義したクラス、またはそのクラスのどのサブクラスの中のどのメンバー関数によっても呼び出すことができます。
- private visibilityが指定されたメンバー関数は、その関数を定義したクラスの中の他のメンバー関数によってのみ呼び出すことができ、サブクラス内のメンバー関数によって呼び出すことはできません。
- デフォルト visibilityが指定されたメンバー関数は、実質的に、同じパッケージ内のすべての他のクラスにとってはpublicであり、パッケージの外部のクラスにとってはprivateです。これはpackage visibilityまたはfriendly visibilityと呼ばれることもあります。
それでは、accessorメソッドの適切なvisibilityは、どのように決めたらよいのでしょうか? 私の経験では、常にaccessorをprotectedにして、サブクラスだけがその属性にアクセスできるようにするように努めるべきです。サブクラスがその属性にアクセスする必要がない場合には、accessorをprivateにするようにしてください。外部クラスまたはオブジェクトが属性にアクセスする必要があるときにかぎり、該当のgetterまたはsetterをpublicにしてください。対応するgetterメソッドとsetterメソッドのvisibilityが異なることはよくあります。Seminar クラスでは、getTitle() メソッドのvisibilityがpublicになっていて、setTitle() メソッドのvisibilityがprivateになっています。図1に示されているように、このsetterメソッドが呼び出されるのは、セミナーの名称の形式 (コース番号、セミナー番号、およびコース名の組み合わせ) を決めるためのgetter内だけです。
図1.Seminar クラスの name 属性に関するgetterおよびsetterメソッド
/**
* Returns the title of the seminar.
* The seminar title is the concatenation of the course number (CCC),
* the seminar number(SSS), and the name of the course(NNN) in the
* format "CCC-SSS NNN"
*
* @return String Title of the seminar
* @modifies yes Initializes the title of the seminar if not yet defined
* @example "CSC 158-2 Introduction to Java Programming"
*/
public String getTitle()
{
String newTitle = new String();
if ( name == null) {
// Build the name
newTitle += course.getNumber() + " ";
newTitle += getNumber();
newTitle += " " + course.getName();
setTitle(newTitle);
}
return this.title;
}
/**
* Sets the title of the seminar
*
* @param title
*
**/
private void setTitle(String title)
{
this.title = title;
} |
必ずしもすべてのaccessorをpublicにする必要がないことを理解することが大切です。ユーザーが適切と判断したvisibilityを定義することができます。残念なことに、このアドバイスはbean以外のJavaクラスにしか当てはまりません。2.x EJB仕様により、Enterprise JavaBean (EJB) のパーシスタント特性のaccessorと同様に、public JavaBean特性を表すaccessorはpublicでなければならないとされているからです。JavaBeanのaccessorメソッドにpublic visibilityを指定しないこともできますので、注意してください。ただしその場合には、それらのaccessorによってカプセル化された属性が、そのbeanのパブリック・インターフェースを介してアクセスすること (これは、まず第一に達成したいことではないかと思われます) ができなくなります。同様に、EJB accessorメソッドをpublicにしないと、それらのaccessorによってカプセル化された属性は持続させることができなくなります。
話題が変わりますが、図1におけるgetTitle() というgetterのインプリメンテーションは、無精な初期化 の例です。この方法を使用した場合、属性の値は、その属性が最初にアクセスされるときに初期化 (設定) されます。この方法の便利な点は、値を入手するための費用負担が、値を必要とするときだけで済むということです。一見すると、この程度のことでは、セミナー名の判別の際にコストがたいして節約できるとは思えないかもしれません。しかし、コース・オブジェクトが別のサーバーに常駐していて、それをパーシスタント記憶域から読み出して、その名前をネットワーク経由で伝送する必要がある場合には、無視できない効果が現れます。無精な初期化の主な欠点は、コードが複雑になることです。これは、該当の属性が定義されているかどうかを検査しなければならず、さらに、まだ定義されていない場合にはその値を入手する必要があるからです。無精な初期化は、一般には、属性の計算または入手に必要なコストが高く (属性が大きく、ネットワーク経由での伝送にかなりの時間を要する場合など)、また、そのオブジェクトをメモリーに記憶するたびに必ずしも属性が必要にはならない場合に使用されます。
図1のsetTitle() というsetterのインプリメンテーションは、命名規則の観点から見て興味深いものです。このトピックについては、"Java 命名規則" で取り上げたことがあります。パラメーターの名前は、インスタンス属性 (フィールド) 自体の名前と同じになり、この例ではtitle となります。これは、いわゆる命名衝突 ですが、幸いなことに、インスタンス属性の前に "this." を付けることによって解決できます。この場合には、テキスト・パラメーターにaTitle やnewTitle のような別の名前を使用しておけばよかったのかもしれません。こうしておくだけで、最初からこうした問題が起こらないようにできます。
accessorメソッドおよびvisibilityの詳細については、以下を参照してください。
-
Building Object Applications That Work: Your Step-By-Step Handbook for Developing Robust Systems with Object Technology、Scott W. Ambler著。New York: Cambridge University Press, 1998.
-
Process Patterns -- Building Large-Scale Systems Using Object Technology、Scott Ambler著。New York: Cambridge University Press, 1998.
-
The Object Primer 2nd Edition、Scott W. Ambler著。New York: Cambridge University Press, 2000.
-
The Unified Process Construction Phase、W. AmblerおよびLarry L. Constantine著。Gilroy, CA: R&D Books, 2000.
-
Enterprise JavaBeans Specification Version 2.0、L.G. DeMichiel、L.U. Yalcinalp、およびS. Krishnan著。2000.
-
The Java Language Specification
、James Gosling、Bill Joy、およびGuy Steele著。Reading, MA: Addison-Wesley Longman, Inc., 1996.
- Advanced Java: Idioms, Pitfalls, Styles and Programming Tips、Chris Laffra著。Upper Saddle River, NJ: Prentice Hall Inc., 1997.
-
Essential Java Style: Patterns for Implementation、Jeff Langr著。Upper Saddle River, NJ: Prentice-Hall PTR, 1999.
-
Java 2 Performance and Idiom Guide: Guidelines for Java 2 Performance, Coding, and Testing
、Craig LarmanおよびRhett Guthrie著。Upper Saddle River, NJ: Prentice Hall Inc., 2000.
-
Object-Oriented Software Construction, Second Edition、Bertrand Meyer著。Upper Saddle River, NJ: Prentice-Hall PTR, 1997.
-
Mastering JavaBeans、Laurence Vanhelsuwe著。San Francisco: Sybex Inc., 1997.
-
The Elements of Java Style、Alan Vermeulen、Scott W. Ambler、Greg Bumgardner、Eldon Metz、Trevor Misfeldt、Jim Shur、およびPatrick Thompson著。New York: Cambridge University Press, 2000.
Scott W. Amblerは、オブジェクト指向ソフトウェア処理の指導、アーキテクチャー・モデリング、およびEnterprise JavaBeans (EJB) 開発を専門とするコンサルタント会社である、Ronin International の社長です。彼は、オブジェクト指向開発に関する本を執筆あるいは共同執筆しています。最近刊行されたものとしては、この記事で要約された主題を詳しく論じた The Object Primer 2nd Edition などがあります。彼の連絡先はscott.ambler@ronin-intl.com およびwww.ambysoft.com にあるサイトです。