Java.use(better);
《目的》
OOP の障害となる「null」の隘路を確認した後で、NullObject パターンを適用して「ポリモフィズム」を促進する術を紹介します。
《動機》
実行時に発生する例外 java.lang.NullPointerException は厄介です。経験を積むほどに発生する頻度は減りますが、それでも皆無にはなりません。
Java/Scala では、null は半人前のオブジェクトとして扱われるので、その対処に苦慮します。Jython/Smalltalk では、null も一人前のオブジェクト(first-class object)として扱えるので、OOP の枠組みで統一できます。
■ NullPointerException の隘路
二分木〔= binary tree〕を扱う典型的な事例で話を進めます。たとえば、
Node tree = new Node(4, new Node(1, new Node(2), new Node(3)), new Node(5)); System.out.println(tree.size()); System.out.println(tree.sum());
これを実行すると、次の結果が得られます。
5 15
この結果から、ノードの総数が 5 に、値の合計が 15 になるのが分ります。
これは、次のように実現します。
class Node { private int value; private Node left; private Node right; Node(int value) { this(value, null, null); } Node(int value, Node left, Node right) { this.value = value; this.left = left; this.right = right; } int size() { return 1 + ((left == null) ? 0 : left.size()) + ((right == null) ? 0 : right.size()); } int sum() { return value + ((left == null) ? 0 : left.sum()) + ((right == null) ? 0 : right.sum()); } }
null を扱うときには、NullPointerException が発生しないように配慮します。それには、if 文や条件演算子 ?: に伴う条件式などが必要です。そのため、コードが複雑で見通しも悪くなるだけでなく、バグの温床になりがちです。
■ NullObject パターンの適用
この問題を解決するために「NullObject パターン」を導入します。すると、
int size() { return 1 + left.size() + right.size(); } int sum() { return value + left.sum() + right.sum(); }
if 文や条件演算子 ?: に伴う条件式が不要になるので、コードが簡潔で見通しも良くなります。
 ̄これは、次のように実現します。
class Node { static final NullNode nullNode = new NullNode(); Node() {} Node(int value) { this(value, nullNode, nullNode); } } class NullNode extends Node { int size() { return 0; } int sum() { return 0; } }
新たなクラス NullNode を用意するとともに、null に代えて、そのインスタンス nullNode を指定します。ここでは、引数を持たないデフォルトコンストラクターが必要になります。
↑ TOP
》作業中です《♪ 八橋(やつはし)