C#の勉強会などというものを部内でやっています。そのとき、本当に理解しているのかなという意地悪な気持ちで、非常に簡単なプログラムの出力結果を、一年生に問うて見ました。
オブジェクト指向プログラミングの壁
オブジェクト指向プログラミングの最初の壁でもあります、参照型と値型の理解ができているかを問います。ソースはC#で書かれていますが、Javaなどでも通用する考え方になります。
第一の課題
これは参照型の意味を理解しているかどうか自体を問うています。
class ArrayTest { static void Main(string[] args) { int[] a = new int[] { 1, 2, 3 }; Test(a); System.Console.WriteLine(a[2]); } static void Test(int[] b) { b[2] = 4; } }
出力は「4」になります。
第二の課題
先ほどの課題の後に出すことで、より間違えさせることができます。stringの連結についての知識もないと解けない問題ですが、そこは本質でないのでヒントとして添えました。これでも、私の後輩はまんまと間違ってくれました。
class StringTest { static void Main(string[] args) { string a = "abc"; // 等価:string a = new string("abc"); Test(a); System.Console.WriteLine(a); } static void Test(string b) { b = b + "def"; // 等価:b = new string(b + "def"); } }
この出力結果は、何でしょうか。ここでは「abc」が出力されます。
C言語風に説明すると、Test(a)で渡されるのは、”abc”が配置されているメモリの先頭番地です。それをbが受け取りました。ここで確認すると、変数bには”abc”の先頭アドレスが入っています。そのbを、”abcdef”の先頭番地に書き換えます(ここで、最初に確保された”abc”の領域と、”abcdef”の領域は待ったく別のものです)。しかし、結局aに格納されている”abc”には何の影響もないことに気づきます。
結論
オブジェクト指向プログラミング初級者で、参照型を勉強している人に出すと、その理解度をチェックすることができると思います。メモリにどのように配置されるか(と、メモリの番地のような考え方)を説明すると、よく理解してもらえました。結局、C/C++言語で直接ポインタを扱ったことがあるのとないでは、想像力が変わってくるのでは、と感じています。