>>205 > たとえばJavaになくってC#にある機能っていうのはJavaの開発してたらなんでやねん、
> なんでないねんていう機能ばかりじゃないか?
> - Cとはちょっと異なる構造体の復活
> Javaで同じValueClassを書くのは無駄にコード量が増えるだけ
> - 列挙型の復活
> これも同じことをしようとすると意味もなくコード量が増える
それは個人の主観と思う。
最近のXP(eXtreme Programming), RUP(Rational Unified Process)な観点から見れば、コード量が増えてでもソースコードは他人に読みやすい方が良いのでは、と思う。
このクラスは継承できる、と思ったら構造体だった、というのも...。
また、構造体や列挙型はUMLで的確に表現できるのでしょか?
>>205 > - 演算子のオーバーローディング
> これは賛否両論あるけど、文字列比較がすっきりしなきゃ言語としてどうかと思う。
> Java: stringA.equals("ABC")
> C#: StringA == "ABC"
> VB.Net: StringA = "ABC"
>=なんかの演算子には等価という意味合いが強く現れるので、構文的にはC#と
>かの方がいいと思わない?
== のほうがすっきりするといえばしますね。
しかし、 == とequalsとを使い分けたいときには面倒なことになると思います。オブジェクトの中にある特定の変数が同じであっても、それを別のものとみなして扱いたいときにはこの機能はちょっと困り者です。
ある==がJavaのequalsに相当するものか、それともJavaの==相当するものなのか、を区別するにはどうすればいいのか、というときに困りそうです。
"Javaの鉄則" という本にはオブジェクトの等値の扱いについて注意すべき項がよく載っている。
例えば、クラスAのオブジェクトと、クラスAを継承したExtendedAのオブジェクトを比較するとき、equalメソッドをどちらのクラスに実装するかを考えなければならない。
また、親クラスと子クラスのオブジェクトを同一とみなすか同かも自分で定義しなければならない。下手に instanceof 修飾子を使うのも良くない。
かといってC#のようなオーバーローディングだけはどちらの等値メソッドを使うかという使い分けをすることができない。
こういう状況にあるときだけ、==と定義したeqauls()メソッドを使い分けてもいいが、"Javaの鉄則" に載っているような状況にでくわしたとき、
equal()メソッドの実装について悩む上に、==の定義についても余計に考えなければならないとか、
勝手に==をオーバーロードされるのは余計なお世話言いたくなる状況も出てくる。
>>206 >を継承するとき、クラスとインターフェースどちらを継承しているかわか
>らないのでインターフェース名の頭にIをつける、これは厄介そう。
> 昔はクラスにCをつけるようにとなっていたよね。
> Javaをしていると継承関係がややこしくてインターフェースかクラス
>かわからなくなるよ。
> でも.Netのように現在は入り組んでないライブラリでも、今後入り組
>んでいくとおもう。
> その時に真価を発揮すると信じているよ。
> どうせならコンパイルオプションではじける設定もほしい
そのときこそUMLが真価を発揮する?
この、頭にCやIをつけるガイドラインは悪しき習慣、ハンガリアン記法の伝統ではないかと。
インターフェースとクラスの区別もUMLクラス図を見れば一目でわかるし、
継承する側は上の説明のとおりimplements, extendsを見れば一目で解るし、
Javadoc API によって生成したドキュメントを見れば一目でわかる。
たいていの場合、複数のクラスやインターフェースは、一つのファイルにつき一つのクラス、インターフェ−スを記述しているはずだ。
そうすれば、同じディレクトリ内に入っているクラス、インターフェースを見るだけで区別にそれほど苦労しない、と思う。
膨大なクラスやインターフェースが沢山あると区別しにくいのではと思うかもしれないが、
同じディレクトリに膨大なのクラスやインターフェースのファイルを入れる方法はソフトウェア管理手法として効率的でない。
デザインパターンを深く学んでいくと、クラスやインターフェースをpackageに入れて分けることの重要性に気づく。
Javaならpackage, C#/C++ならnamespaceで管理し、package, namespaceの違いはディレクトリ(フォルダ)の違いとして判断させる。
>>207 > あと忘れ物だ
> !!!throws!!!
> これってあんまり役に立っていないと最近思う。
> RuntimeExceptionはつかまないし、ほとんどつかみたいのはruntimeだ
>って。 この機能はスパッと切って正解だったと思うよ。
これは超重要ですよ!!
C#でこれ無くしたことはある意味、ミッションクリティカルで大規模なプログラミングでは致命的ではないかと。
RuntimeException 以外にも、特にファイル入出力では FileNotFuondExceptionとかIOExceptionとかかなり重要なものもありますよ。
throwsはずすのはさすがにまずと思われます。
C#では すべてのメソッドは Javaの throws Exception に相当することをやっているというわけで、どの例外が投げ出されるか具体的に判別できなくなります。
throwsに加える例外はできる限り詳細に並べよ、というのが(これまた) "Javaの鉄則" に載っています。
>>207 class AException extends Exception {}
class AAException extends AException {}
class AAAException extends AAException {}
class ExceptionDemo {
method() throws Exception {
//何かの実装
throw new Exception();
//何かの実装
throw new AException();
//何かの実装
throw new AAException();
}
}
これではmethod()がAAExceptionやAExceptionをスローしたとしても返ってるのはExceptionのみ。なぜなら、これらの例外クラスはExceptionのサブクラスで同一とみなされる。
具体的な例外を知りたいときは以下のようにしなければならない。
class ExceptionDemo {
method() throws Exception, AException, AAException {
//何かの実装...大幅に省略
}
というわけでthrowsは重要であり、C#でこれがなくなったということはバグの検出を非常に困難にしているのではないかと思います。
throws節をはずしたことによる問題点が議論されています。
http://www.users.gr.jp/ml/archive/CS/391.asp 簡単なプログラムでははずした方がよくても
複雑になると、これをはずすというのはバグ捕りのしやすさに影響が出ると思われます。
万が一のことを考えるとthrows節はあった方が良いと思います。
throws節で例外クラスを指定しないということは、
他人がコーディングしたC#のコードを解析、ライブラリをインポートするときにどのような例外がスローされるのか想定しにくい。
throwsされる例外クラスからどのような例外が起こりうるかと想定してコーディングできなくなります。
throws節はプログラマに契約を守らせる上で重要だと思います。
C#が発表されたとき、オブジェクト指向を超越した、エージェント指向な、アスペクト指向なプログラミング言語が出現すると期待していたんですが、全然違っていますね。これも C#が .NETによる多言語の互換性のために作られたということなのですね。
.NETの中心に据えられていると考えられるC#についてさらに意見を追加
virtual 修飾子は余分。
virtual修飾子をつけつけないに影響する速度の問題など気にするべきでない。
これも.NET政策のためにC++との下位互換性維持のために速度重視のためにあえて付けられたと推測。
Javaだとvirtualを意図しないときはfinal属性をつける
速度問題よりもむしろ、UMLにマッチするような、すっきりしたソースコードを書くほうが重要。
interfaceで宣言されてるメソッドをinterfaceを介して呼ぶ出すなら
常にvirtualメソッドと見なされるので、クラス中のメソッドの定義のデフォ
ルトがvirtualか否かはそれほど重要な問題ではない、ともいえる
デザインパターンを意識するならば、構造体、列挙型は極力使わないようにすべきと思います。
ついでに、#がトリップパスに代わったので修正。
>>207 > !!!ボクシング/アンボクシング&すべてがobjectを継承していない!!!
> javaでは値型が特殊な変数になっているためにVectorなんかにそのま
>ま入れれない。
> これって誰も言わないんだけど致命的な設計ミスじゃない?
ボクシング/アンボクシング
自動的に変換するというのも奇異です。
これも過去の言語の型との互換性をどうにかしたかったために用意されたものではないかと。
unboxingについてよく理解していないのですが、ラップクラスに相当するものを呼び出さなくても自動的に変換できることでコード量が短縮できるという利点があるだけに見えます。
値型をどうにかするには、dobule型なら、DoubleクラスなどでラップしてからVectorに add() すれば、C#よりコード量がちょっと多いことを除いて同じことではないかと思います。
この程度のコード量などオブジェクト指向的な観点から見れば気にするべきではないと思います。
この程度のコード量の多さを気にしていてはインターフェースや抽象クラス、例が処理のtry-catch節などまともにかいていられません == オブジェクト指向性を失う。
>>207 Smalltalkから見たらJavaのプリミティブ型というのは失敗だったのですね。
型はすべて参照型でint, long doubleなど使わずに最初からInteger, Long, Doubleなどのラップクラスのみで定義すべきだったということですね。
私にはJavaにプリミティブ型(値型)が存在すること自体が致命的なミスではないかと思います。
型キャストも簡単にできてしまうのもミスだと思います。
J2SE1.5からJavaGenericによりC++のテンプレートに相当する機能が使えるようになりこれによりコレクション系インターフェースの型キャスト問題を解消できると期待しています。
Javaのプリミティブ型は唯一Objectクラスを継承しないものですね。
結論をいうと、 .NETというもは古い言語プログラマのため、古い言語を再利用したいためにあるものということが、C#の仕様からわかります。
新規にプロジェクトを開始するときに一種類の言語しか使う予定が無い、古い言語で書かれたコードもすべて新しい言語で書き直す方針、ならばC#よりJavaのほうが良いかな、と思える。
古い言語を再利用し、書き直さずに利用する予定がある場合にはJavaよりC#が向いている、と思える。