特集

私がJavaからC#に乗り換えた10の理由

日本ユニシス 尾島 良司
2003/07/05
Page1 Page2 Page3 Page4

- 理由06 - interface

 ソートするために、大小を比較するインターフェイスを定義する場合を考えてみよう。汎用的にするためには、あらゆるクラスのインスタンスに対応できるように比較メソッドの引数の型はObject型になるだろう。

 ただし、社員と商品の大小比較などはあり得ないので、引数の型がObjectであっても実際に比較可能なのは、たいてい自分と同じクラスもしくはそのサブ・クラスのインスタンスに限定される。この結果どうなるかといえば、“実行時”に型の不整合で失敗するプログラムが出来上がってしまうのである。

 Javaより前、Smalltalkのころのオブジェクト指向では、実行してみるまでうまくいくか分からないのは当たり前だった。強い型制約がなかったためである。Cの流れを引き継ぎつつブジェクト指向を取り入れたC++では、強い型制約を採用してコンパイル時に型の不整合をチェックできるようにした。当時は「柔軟なSmalltalkと安全なC++」という評価をよく見掛けたものである。

 閑話休題。そもそもインターフェイスは型に基づく安全なプログラミングをするためのものである。そのインターフェイスを採用したがためにその安全性が破壊されてしまうのだ。本末転倒。テスト・フェイズが長期化して納期に間に合わなくなる。実に嘆かわしい事態だ。

 この問題は、安全な型のみを受け入れるメソッドを作成して、それを使用するように強制することで解決できる。C#なら、「インターフェイス・メソッドの明示的な実装」という機能を使用すればこの安全が手に入る。納期が厳しいプロジェクトをこなしているプログラマなら、C#への乗り換えが実に魅力的に映るのではないだろうか?

 以下にインターフェイス・メソッドの明示的な実装の概要を解説する。理解を容易にするためにまずはコード例を示す。

public class MyClass: IComparable
{
  //  このメソッドはIComparableとは関係ない。
  public int CompareTo(MyClass myClass)
  {
    //  比較のためのコード。
  }

  //  インターフェイス・メソッドの明示的な実装。
  int IComparable.CompareTo(object obj)
  {
    return CompareTo((MyClass)obj);
  }
}

public class C
{
  public static void Main(string[] args)
  {
    MyClass myClass = new MyClass();

    //  バグのあるコード。コンパイル・エラーになる。
    if (myClass.CompareTo(new object())) { }

    //  バグのあるコードだが、実行するまでエラーにならない。
    if (((IComparable)myClass).CompareTo(new object())) { }
  }
}
「インターフェイス・メソッドの明示的な実装」のコード例

 「int IComparable.CompareTo(object obj)」の部分がインターフェイス・メソッドの明示的な実装である。このメソッドはpublicではないことに注意していただきたい。このメソッドはIComparable型の変数で参照している場合にしか呼べないのである。MyClass型の変数で参照している場合にはMyClass型を引数に取る方のメソッドしか呼べないのだ。だから、myClass.CompareTo(new object())はコンパイル・エラーになる。そして、コンパイル時にエラーを検出できれば、テストの期間を短縮できるのである。

- 理由07 - virtualとoverride

 優秀なJavaプログラマが書いたソース・コードを見ると、やたらと「final」が目に付く。Javaでは、finalを指定することでサブ・クラスによるメソッドのオーバーライドを禁止できる。オーバーライドによる振る舞いの変更はたしかに便利だが、不適切なオーバーライドによるバグの可能性ももたらす。つまり、ポリモルフィズムが不要な部分では、finalを指定した方が安全性を向上させられるのだ。

 逆をいえば、例えば私のような凡庸なプログラマが書いたソース・コード(finalがほとんどない)では、ポリモルフィズムを使用していない部分に不要な危険が潜んでいる。そして、ポリモルフィズムを使用しない部分の割合はかなり多い。はっきりいってしまえば、通常のビジネス・アプリケーションではポリモルフィズムを使う部分などほとんどないのである。結果として、多くの場合に無駄な危険を冒すことになる。実に嘆かわしい。

 これは、Javaのデフォルトが「ポリモルフィズムあり」になっていることに起因する。C#では違う。C#のデフォルトは「ポリモルフィズムなし」であり、ポリモルフィズムを使いたい場合にvirtualとoverrideを指定するのだ。C#なら無駄な危険を冒さなくて済む。どうだろう、そろそろC#に乗り換えたくなってきたのではないだろうか?

 以下にC#でポリモルフィズムを使う場合の概要を解説する。例によってコードを示す。

public class Super
{
  //  ポリモルフィズムを適用したいメソッドには、
  //  virtualを付けなければならない。

  public virtual void VirtualMethod() { }
}

public class Sub: Super
{
  //  スーパー・クラスのメソッドの振る舞いを変更したい場合には、
  //  overrideを付けなければならない。

  public override void VirtualMethod() { }
}
virtualとoverrideによりポリモルフィズムを使用したコード例

 コメントに書いたとおり、スーパー・クラスのメソッドにvirtual、サブ・クラスのメソッドにはoverrideを付けなければC#ではポリモルフィズムを使用できない。面倒だと感じるかもしれない。しかし、ほとんどのメソッドにfinalを付けるより、ポリモルフィズムのための少数のメソッドにvirtual/overrideを記述する方が作業量は大幅に少なくて済むのである。

- 理由08 - #if

 Javaには条件コンパイルがない。finalな変数を使用してif文を書き、コンパイラの最適化でif文が実行されなくなるのを祈るしかない。確かに実用上はこれで問題ないのだが、私はずっとこの方式が嫌いだった。ロジックとして意味があるコードと同じ記述なので、ソース・コードの保守性が落ちてしまうのである。ささいなことだが、納期が厳しい場合にはこんなささいなことでも嘆かわしいと感じるものだ。

 C#には私が願ってやまなかった条件コンパイルがある。私と同じことを考えているJavaプログラマは多いのではないかと思う。そのような人々にとってC#は魅力的なのではないだろうか?

 以下に条件コンパイルのコード例を載せる。

#define DEBUG

using System;

public class C
{
  public static void Main()
  {
#if DEBUG
    //  DEBUGが定義されていない場合はコンパイル対象外になる。

    Console.WriteLine("デバッグ中");
#endif
  }
}
条件コンパイルのコード例

 #defineで変数(シンボル)を定義できる。#ifで指定した変数が#defineされていない場合は、#ifから#endifまではコンパイルの対象外になる。条件コンパイルはデバッグの際には非常に役に立つ機能である。

- 理由09 - Visual Studio .NET

 最近のJavaの統合開発環境は非常によくできている。eclipseなどは無料でありながらVisual Studio .NETに負けないくらい高機能だ。Visual Studio .NETを使っているときに、Javaの統合開発環境であるIDEAのあの機能があったらと感じることすらある。

 しかし、いくらJavaの統合開発環境が高機能であっても、やはりVisual Studio .NETの方が便利だと考える。個々の機能の優劣ではない。Windows XPとVisual Studio .NETがあれば開発に必要なものがすべてそろうところが便利なのである。

 Javaの場合、Java2 SDKをセットアップし、各種ライブラリをセットアップし、eclipseをセットアップし、アプリケーション・サーバをセットアップし、RDBMS(Relational Database Management System)をセットアップしなければならない。セットアップが終了したら、全体の整合性が取れるように苦労して環境を整備しなければならない。面倒すぎる。嘆かわしい話だ。

 Visual Studio .NETなら、Visual Studio .NETをセットアップするだけで作業は終了なのである。Visual Studio .NETにはSQL Serverと同等の機能を持つMSDEが付属している。MSDEを使うのならノート・パソコン1台で自宅でも開発できる。過酷な労働を強いられているプログラマにとって、これはあまりに魅力的なのではないだろうか?

- 理由10 - Javaが嫌になった

 正確には「一部のJavaコミュニティの存在が嫌になった」である。

 Javaプログラマには、高いスキルを持った理想主義者が数多く存在する。彼らは、最新の技術を用いて効率的なソリューションを創造している。JakartaeclipseAspectJなどはその結果の最たるものだろう。いくら偏屈な私といえども、これらのコミュニティとその成果は賞賛せざるを得ない。C#な私でも、いまだにJavaのメーリング・リストや雑誌の購読をやめられないでいる。

 しかし、理想主義者の高尚な成果が、スキルを持たない人々が大風呂敷を広げるための道具として使われていることも悲しい事実である。ビジネス・アプリケーションにおいては限定的な効果しか果たせないはずのフレームワークやコンポーネントという言葉を使用してひともうけを狙う、技術者とは呼べないような人々のコミュニティがJavaには多い。

 Strutsでアーキテクチャを強制するとの表現を聞くことがあるが、正しくは“StrutsでWebフロント・エンド部分のアーキテクチャを強制する”である。StrutsはModelの内部構造を何も規定していないためだ。EntityBeanでオブジェクト指向分析/設計の結果をコンポーネントにマップするというが、現在のEntityBeanはRDBMSのラッパーでしかない。ビジネス・コンポーネントの流通という話を聞くが、成功したという話はいまだに聞いたことがない。ドメインが異なればコンポーネントは再利用できないのだ。

 玉石混交が世の常とはいえ、一部のJavaコミュニティはひどすぎる。しかもなぜかそれらのコミュニティがビジネス上は強い影響力を持っていたりするのだ。実に嘆かわしい話だと思う。

 C#では状況が違う。元締めであるMicrosoftが理想主義者ではなく、現実主義者なのだ。スキルがなければ現実を語ることはできない。夢物語を語る余地はC#にはない。少々夢がない話ではあるが、目の前のプロジェクトを現実の世界で成功させなければならない技術者にとって、C#は魅力的な選択肢なのではないだろうか?


 INDEX
  [特集]私がJavaからC#に乗り換えた10の理由
     1.struct、delegate
     2.property、custom attribute、thread
   3.interface、virtualとoverride、#if、Visual Studio .NET、Javaが嫌になった
     4.私が思うC#の“正しい”使い方
 
更新履歴
【2003/07/16】本ページの内容に以下のような誤りがありました。お詫びして訂正させていただきます。

- 理由07 - virtualとoverride

 優秀なJavaプログラマが書いたソース・コードを見ると、やたらと「final」が目に付く。Javaでは、finalなメソッドはポリモルフィズムの対象にならない。ポリモルフィズムが不要な部分では、finalを指定した方が実行効率を向上させられるのだ。

 逆をいえば、例えば私のような凡庸なプログラマが書いたソース・コードでは、ポリモルフィズムを使用していない部分でCPUを無駄遣いしているのだ。そして、ポリモルフィズムを使用しない部分の割合はかなり多い。はっきりいってしまえば、通常のビジネス・アプリケーションではポリモルフィズムを使う部分などほとんどないのである。結果として、多くの場合に無駄にCPUが使われていることになる。実に嘆かわしい。

 これは、Javaのデフォルトが「ポリモルフィズムあり」になっていることに原因がある。C#では違う。C#のデフォルトは「ポリモルフィズムなし」であり、ポリモルフィズムを使いたい場合にvirtualとoverrideを指定するのだ。C#なら無駄にCPUを使う可能性が減る。どうだろう、そろそろC#に乗り換えたくなってきたのではないだろうか?

 優秀なJavaプログラマが書いたソース・コードを見ると、やたらと「final」が目に付く。Javaでは、finalを指定することでサブ・クラスによるメソッドのオーバーライドを禁止できる。オーバーライドによる振る舞いの変更はたしかに便利だが、不適切なオーバーライドによるバグの可能性ももたらす。つまり、ポリモルフィズムが不要な部分では、finalを指定した方が安全性を向上させられるのだ。

 逆をいえば、例えば私のような凡庸なプログラマが書いたソース・コード(finalがほとんどない)では、ポリモルフィズムを使用していない部分に不要な危険が潜んでいる。そして、ポリモルフィズムを使用しない部分の割合はかなり多い。はっきりいってしまえば、通常のビジネス・アプリケーションではポリモルフィズムを使う部分などほとんどないのである。結果として、多くの場合に無駄な危険を冒すことになる。実に嘆かわしい。

 これは、Javaのデフォルトが「ポリモルフィズムあり」になっていることに起因する。C#では違う。C#のデフォルトは「ポリモルフィズムなし」であり、ポリモルフィズムを使いたい場合にvirtualとoverrideを指定するのだ。C#なら無駄な危険を冒さなくて済む。どうだろう、そろそろC#に乗り換えたくなってきたのではないだろうか?


スーパー・クラスのメソッドの動作を変更したい場合には、
スーパー・クラスのメソッドの振る舞いを変更したい場合には、

しかし、実行効率を上げるためにほとんどのメソッドにfinalを付けるより、ポリモルフィズムのための少数のメソッドにvirtual/overrideを記述する方が作業量は大幅に少なくて済むのである。
しかし、ほとんどのメソッドにfinalを付けるより、ポリモルフィズムのための少数のメソッドにvirtual/overrideを記述する方が作業量は大幅に少なくて済むのである。



Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間