はじめに
本連載の初回は、プログラミング歴6か月の本間が担当します。初心者の皆さんと同じ立場から記述しますので、よろしくお願いします。
Java meet Python。そして、Jythonが産まれました。Jythonでは、JavaBeansに準拠するJavaのリソースを再利用するときに、便利な機能を提供します。今回は、一粒で二度美味しい、Jythonの魅力(旨味)を紹介します。
対象読者
こんな症状を抱えているなら……。
- JavaBeansに準拠した既存の資産(負債?)は今後も運用したい。
- しかし、そのメンテナンスには多大な費用が掛かる。
- Javaの開発効率の悪さにストレスが溜まる。

JavaBeans:値の獲得と設定
JavaBeansでは、ある特性を獲得/設定するためのプロトコルとして、それぞれ、getter/setterメソッドと呼ばれるものを規定しています。
public class NameBeans { private String name; public Beans() { this.name = "John"; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
Javaで記述したクラスNameBeansには、String型の特性nameを定義しています。これに伴い、その値を獲得するメソッドgetNameと、その値を設定するメソッドsetNameが定義されます。このとき、get/setに続く名前は大文字で始めます。また、getメソッドのリターン値と、setメソッドの引数とは、同じ型になります。
Javaモジュールを取り込むには
>>> import NameBeans
Javaで記述したモジュールを取り込むには、importを利用します。すると、クラスファイルNameBeans.classの情報に、Jythonからアクセスできます。
>>> dir(NameBeans) ['getName', 'name', 'setName']
組み込み関数dirを使って、クラスNameBeansに固有の情報を調べると、メソッドgetName/setNameが定義されているのが分かります。
>>> dir(NameBeans()) ['__init__', 'class', 'equals', 'getClass', 'getName', 'hashCode','name', 'notify', 'notifyAll', 'setName', 'toString', 'wait']
クラスNameBeansのインスタンスに固有の情報を調べると、先に加えて、親クラスObjectから継承したメソッドgetClassなども含まれるのが分かります。
NameBeansはクラスオブジェクトを、式NameBeans()はインスタンスオブジェクトを、それぞれ参照します。クラス/インスタンスに共通の概念モデルを持つ、その世界の住人だけに許された特権と言えます。洗練されたOOPの世界では、もうJavaの常識は通用しません。Introspectorを使って
from java.beans import Introspector
def properties(bean):
info = Introspector.getBeanInfo(bean)
return [e.name for e in info.propertyDescriptors]
>>> properties(NameBeans)
['class', 'name']
パッケージjava.beansを利用すると、JavaBeansに準拠する情報が得られます。ここでは、クラスNameBeansに固有の特性nameのほかに、親クラスObjectで定義されたメソッドgetClassから類推される、特性classが得られます。
JavaBeansの属性にアクセスする
>>> bean = NameBeans() >>> bean.name John
Jythonでは、Pythonのスタイルを併用できます。メソッドgetNameを使わなくても、属性名nameを使って、Javaで記述した特性値を獲得できます。
>>> bean.name += " Doe" >>> bean.name John Doe
同様に、メソッドsetNameを使わなくても、代入演算子+=を使って、新しい値を設定できます。これは、bean.name=bean.name+"Doe"と等価です。Javaのスタイルを踏襲して、getter/setterを使った式bean.setName(bean.getName()+"Doe")と比べて、簡潔で見通しのよいコードを記述できます。
>>> bean = NameBeans(name="Jane Doe") >>> bean.name Jane Doe
さらに、キーワード引数name=を使うと、メソッド呼び出しsetName()と同じ効果が得られます。ただし、この方法は、コンストラクタ呼び出しには適用できますが、通常のメソッド呼び出しには適用できません。

'name', 'notify', 'notifyAll', 'setName', 'toString', 'wait']