@ITの
文字列をequalsで判定する時
で行われた議論に対する私なりの考察の第二回です。
議論のテーマは
です。前回エントリでは構文的な分析について述べました。
"hoge".equals(str)は読みにくいのか?
そもそも「読みやすい/読みにくい」とは何かというのが難しいテーマですね。
その人がどのような知識をもっているか、どのような思考回路をしているのか、
そういったもので変わってきますから、「主観」の一言で済まされてしまいそうな話題です。
通常、Javaの言語を学ぶ過程で、変数というものは早期に教えられます。
そして、メソッドの呼び出しについても早期に教えられることでしょう。
プリミティブ型とオブジェクト型の違いは初期に教わると思いますが、
それがしっくりくるまでには時間を要します。
型とインスタンスの概念について、自信を持って回答できるまでには相応の訓練ないし経験が必要です。
定数に対するメソッド呼出しが不可能と思いこむ理由
さて、「オブジェクト型 - プリミティブ型」というパラダイムと、
「変数 - 定数」というパラダイムを合わせることで4つの事例が導出できます。
// オブジェクト型 - 変数
String str = "hoge";
str.toString();
// オブジェクト型 - 定数
"hoge".toString();
// プリミティブ型 - 変数
int i = 0;
i.toString();
// プリミティブ型 - 定数
0.toString();
このうち、プリミティブ型の2つのコード例はコンパイルエラーとなります。
注目したいのは、オブジェクト型とプリミティブ型の「変数」の場合のメソッド呼出しは
いずれもコード的には同一の外見をしている点です。変数名が同じであれば
String hoge = "hoge";
hoge.toString();
int hoge = 0;
hoge.toString();
というように、まったく同じ外見をします。そして、一方はコンパイル可能で、一方はコンパイルエラーとなります。
対してプリミティブ型の定数に対してのメソッド呼出しというのは外見がそもそも違うので容易に識別できます。
256.toString();
0xCAFEBABE.toString();
ですから、「定数に対してメソッド呼出しをすることはできない」と理解してしまうことは自然でしょう。
文字列定数という「定数だがオブジェクトである」という例外を知るまでは。
文字列定数のメソッド呼出を知らずともあまり困らない
オブジェクトに対してメソッド呼出しを行うことは、初期に理解していることと思います。
そうなると、「文字列定数のメソッド呼出し」を理解するために必要なのは、
文字列定数が「特殊な何か」という理解から、「オブジェクトの一種」であるという汎用的でより抽象的な
概念での理解ではないかと思われます。
といっても、そんなに難しい話ではなくて、「"hoge"はStringの変数に代入できることからも
分かるようにオブジェクトであるわけだから、"hoge".toString()といったメソッド呼出しが可能だ」という程度の
説明で「そうなんだ」と理解できる程度には簡単な話題です。
ただ、理解がたやすいことと、広く知られているかは別問題。
触れる機会がなければそのような概念を理解する必要はなく、
「定数からメソッド呼出しはできない」という誤った理解でも問題がない。
自分の知りうる世界ではその理解でもなんらの矛盾を起こさないのですから。
オブジェクト型のいろいろ
触れる機会がないなら、誤解していようが矛盾に遭遇しないので対して問題が発生しないことは述べました。
オブジェクトであればメソッド呼出しができるわけですが、誤って理解していても困らない例をもう少し挙げてみましょう。
int[] array = new int[]{1, 2, 3};
array.toString();
これは、配列もまたオブジェクトである例です。変数arrayはプリミティブ型であるintの配列ですが、
toString()といったjava.lang.Objectのメソッドを呼び出すことができます。
「配列もまたオブジェクトである」という正しい知識を持たず、「配列は配列」と理解していてもあまり困ることはありません。
配列をjava.lang.Objectとして扱わなければならない状況というものがそもそもレアですから、
誤った理解をしていたとしても、そこから生まれ来る矛盾に遭遇することはなかなかありません。
また、JavaSE 5.0からは列挙型というものが用意されました。
public enum Hoge {
ENUM_1,
ENUM_2,
ENUM_3
}
この列挙型もまたオブジェクトですから、
Hoge.ENUM_1.toString();
というように記述可能です。が、列挙型の場合は見た目が定数っぽく見えないですから、
「定数はメソッド呼出しができない」という誤った理解でも違和感を感じないかもしれません。
読みにくさの理由
以上のことをまとめてみましょう。
(1)学習の過程の関連からstr.toString()が理解できるが、"hoge".toString()が理解できない理解状況存在する。
これは"hoge".toString()は理解できるがstr.toString()が理解できないという理解状況にある人というものが
存在しないことから納得できる事項であるでしょう。
(2)上記「定数はメソッド呼出しができない」の誤解をしている可能性。
プリミティブ型のリテラルからのメソッド呼出しはできませんが、仮にそのような表記をすれば
外観からして違うものとなることは述べたとおりです。
また、このような誤解をしていたとしても、困らないことが多いと述べました。つまり、誤解が訂正されない可能性があります。
この誤解が先入観として沁み渡っているとすれば、文字列リテラルに対してのメソッド呼出しは異質に思えるのではないでしょうか。
この(1)および(2)から「読みにくい」という感情をある程度は説明できると思われます。
またこの他に、今までの経験から違和感を覚える可能性が考えられます。
(3)「定数からメソッド呼出しをすることに触れていない」可能性。
この場合、なじみのない記法ということになりますから、「違和感」を感じると思われます。
そのようなソースにたくさん触れるとなじむ可能性があります。
(4)「若者の言葉の乱れ」の話題ように、自分の習慣にない記法に対して嫌悪感を持つ可能性。
私も「重複」を「じゅうふく」と読むのだけはどうにも許せないのですが、
このように自分のやらないことに対して嫌悪感を持つのは人間心理としては自然なことです。
これらの事象から「読みにくい」「違和感を覚える」「気持ち悪い」という感想が出るのではないでしょうか。
これらいずれにも当てはまらないが、「違和感を覚える」人もいるかもしれません。
ここで挙げたものは、「違和感を覚える原因として考えられること」ですが、
当然、そのすべてを列挙しているわけではありません。
しかし、こういった原因によって感情が作られると分析することで、
「そういった感情を覚える自分」といったものに対しても向かいやすくなります。
このエントリでとりあげられなかったこと
このエントリでは文字列リテラルのメソッド呼出しという観点で分析をしました。
そのため、メソッドの例としてはtoString()を用いています。
@ITの方では意味による「読みにくさ」が指摘されています。
つまり、"hoge".equals(str)というのは「"hoge"がstrと等しい場合」という意味になりますね。
日常の思考では「strが"hoge"と等しい」という考え方をするため、捉えにくいという意見です。
この点の考察はまた別途行いたいと思います。
投稿日時 : 2008年2月16日 22:00