通常、Java開発にはC#/。NETよりも多くのサブクラスが含まれますか?


34

最近、Androidの開発を検討し始めました。これにより、私はJavaソフトウェア開発の世界に戻ってきました。私が最後にJavaで作業したときは、OOPを(私が思うに)今ほど理解していないことを認めます。

私のキャリアでは主にC#を使用していましたが、継承がJavaとC#を使用する方法に驚くべき違いがあることに気付きました。

C#では、ほとんどの状況で継承を回避できるように思われました。通常、当面のタスクは、.NETフレームワークの具体的なクラスを使用して実現できます

Javaでは、コードサンプルから収集したものから、Javaフレームワークは多くのインターフェイスまたは抽象クラスを提供し、開発者が実装/拡張することを意図しているようです。

これは、スタイルにまで煮詰めるには大きすぎる違いのようです。この背後にある理由は何ですか?これを理解するまで、きれいなJavaコードを書くことはできないと思います。

また、これはAndroid SDKだけに限定されていますか?これはOOPに対するJava全体のアプローチですか?

または別の言い方をすれば、

これら2つの言語の設計について、他の言語よりも多かれ少なかれ継承を使用しているように思われますか?

言語が継承を同一に扱い、私の観察が有効であると仮定すると、これは言語ではなくフレームワーク/ライブラリの設計に関連することを意味します。この種のデザインの動機は何でしょうか?


1
それは本当です。Javaのインターフェースは多すぎます。この開発者の動作が特定の言語に共通している理由を知りたいです。これは、Javaプロジェクトでは他のどのプロジェクトよりも頻繁に発生しています。意見だけでなく、これには理由がなければなりません。
-Reactgular

1
@MathewFoscariniそれはあなたの意見だけです。私が参加したJavaプロジェクトでは、開発者はペストのように継承を避ける傾向がありました。ここには信頼できるものは何もなく、私の意見だけです。投票したいですか?
gnat

2
Javaでは、ほとんどの場合、あるクラスを別のクラスから派生させる必要はありません。代わりに、インターフェイスを実装して多態性を実現し、合成オブジェクトを実装し、メソッド呼び出しをプロキシして機能を実現できます。
DwB

1
@ThinkingMedia一般に、JavaはOSSの熱狂者/純粋主義者に追われています。学問的原則が最優先事項です。.Net開発者は、仕事を成し遂げることを心配するプラグマティストです。彼らは最もクリーンなコードよりも作業コードを重視しています。
アンディ

回答:


31

これは、スタイルにまで煮詰めるには大きすぎる違いのようです。この背後にある理由は何ですか?

私の理解では、それは主単なる文体的な決定であるということです。まあ、おそらくスタイルではなく、言語/環境のイディオム。Java標準ライブラリの開発者は1つの設計ガイドラインに従い、.NET開発者は別の設計ガイドラインに従いました(ただし、Javaのアプローチがどのように機能するかを見ることができました)。

実際の言語では、継承を奨励または思いとどまらせることはほとんどありません。関連性があると思うのは、次の2つだけです。

  1. .NETは、一般的でないコードが多く実装される前に、ジェネリックをその寿命の早い時期に導入しました。別の方法は、特殊化されたものを入力するための多くの継承です。

  2. 大きな変更点は、.NETがデリゲートをサポートしたことです。Javaでは、最も基本的な変数機能を提供するために(匿名の)継承にこだわっています。これにより、デリゲートを活用するか、Javaでデリゲートを行うために必要な厄介な継承構造を回避するためのコード設計方法に比較的大きな違いが生じます。


3
この答えは非常にもっともらしい説明を提供すると思います。特にデリゲートの代わりに匿名継承についてのポイント。私はこれをよく観察しました。ありがとう。
メタファイト

3
.NET 3.5で導入された匿名型とラムダ構文/式ツリーを忘れないでください。そしてもちろん、.NET 4のオプトイン動的型付けは、ほぼ間違いなく、パラダイムが混在した言語であり、厳密にはオブジェクト指向ではありません。
アーロンノート

はい、私の経験では、両方を使用した(同じ人々が両方の言語を使用する混合プロジェクトを含む)人々は、Javaをコーディングするときに多数の小さなクラスを使用する傾向があり、少数の大きなクラス(神クラスに向かう傾向がある) C#を使用します。両方で同じスタイルを使用して同じものを意図的にプロトタイピングすると、同様の数のクラスになります(部分クラスを使用すると、C#を使用している場合でもより多くのコードファイルになります)。
14

6

これらは、特にこの分野では非常に異なる言語です。クラスがあるとしましょう。この場合、ユーザーコントロール(テキストボックスなど)にします。UIControlと呼びます。次に、これを別のクラスに配置します。この場合、この例ではUIを使用しているため、CleverPanelクラスと呼びます。CleverPanelインスタンスは、さまざまな理由でUIControlインスタンスで発生していることを知りたいと思うでしょう。これを行う方法?

C#の基本的なアプローチは、さまざまなイベントをチェックし、各興味深いイベントがトリガーされたときに実行されるメソッドを設定することです。イベントのないJavaでは、通常の解決策は、さまざまな「イベント」処理メソッドを持つオブジェクトをUIControlメソッドに渡すことです。

boolean  stillNeedIt =  ... ;
uiControl.whenSomethingHappens( new DoSomething()  {
    public void resized( Rectangle r )  { ... }
    public boolean canICloseNow()  { return !stillNeedIt; }
    public void closed()  { ... }
    ...
} );

これまでのところ、C#とJavaの違いはそれほど大きくありません。ただし、C#では不要なDoSomethingインターフェイスがあります。また、このインターフェイスには、ほとんどの場合必要のない多くのメソッドが含まれている場合があります。C#では、そのイベントを処理しません。Javaでは、すべてのインターフェイスメソッドDoSomethingAdapterにnull実装を提供するクラスを作成します。次に、DoSomethingをDoSomethingAdapterに置き換えます。クリーンコンパイルのためにメソッドを記述する必要はありません。プログラムを正しく動作させるために必要なメソッドをオーバーライドするだけです。そのため、C#のイベントで行ったことと一致させるために、インターフェイスが必要になり、Javaの継承使用することになります。

これは例であり、包括的な説明ではありませんが、C#ではなくJavaに多くの継承がある理由の基本を示しています。

さて、なぜJavaはこのように機能するのですか?柔軟性。whenSomethingHappensに渡されたオブジェクトは、完全に別の場所からCleverPanelに渡された可能性があります。CleverWindowオブジェクトをどこかで支援するために、いくつかのCleverPanelインスタンスがUIControlのようなオブジェクトに渡す必要があるかもしれません。 または Uicontrolのは、のいずれかにそれを引き渡すことができ、そのコンポーネント。

さらに、アダプターの代わりに、その背後に数千行のコードがあるDoSomething実装が存在する場合があります。その新しいインスタンスを作成て渡すことができます。1つのメソッドをオーバーライドする必要がある場合があります。Javaでの一般的なトリックは、次のようなメソッドを持つ大きなクラスを持つことです。

public class BigClass implements DoSomething  {
    ...many long methods...
    protected int getDiameter()  { return 5; }
}

それからCleverlPanelで:

uiControl.whenSomethingHappens( new BigClass()  {
    @Override
    public int getDiameter()  { return UIPanel.currentDiameter; }
} );

オープンソースのJavaプラットフォームはこれを多く行います。これは、プログラマーがより多くのことをするように促す傾向があります。私は言語の基本的なデザインは、Sunのフレームワークの設計の背後にあると思いますし、 Javaのプログラマの際に技術を使用して、後ろにいないフレームワークを使用しました。

Javaでクラスをその場で簡単に作成できます。クラスは、匿名または名前付きで、1つのメソッドに深く埋め込まれた1つの小さなコードブロックでのみ参照する必要があります。完全に新規に作成することも、非常に大きな既存のクラスを少し変更することによって作成することもできます。(既存のクラスは、独自のファイルでトップレベルにすることも、トップレベルのクラスにネストすることも、コードの単一ブロック内でのみ定義することもできます)。新しいクラスインスタンスは、作成するオブジェクトのすべてのデータにフルアクセスできます。そして、新しいインスタンスを渡してプログラム全体で使用し、それを作成したオブジェクトを表すことができます。

(余談ですが、ここでは(Javaの他の場所でのように)継承の大きな用途は単にDRYの目的であることに注意してください。異なるクラスが同じコードを再利用できるようにします。 )

繰り返しますが、これは包括的な議論ではありません。ここで表面を引っ掻いているだけです。しかし、はい、JavaとC#の間で継承が使用される方法には驚くべき違いがあります。 この点で、それらは非常に異なる言語です。それはあなたの想像力ではありません。


注:空の実装でいっぱいの抽象クラスを拡張することにより、何もしないメソッドを提供する必要を回避できます。このようにして、何かを行うメソッドを選択的にオーバーライドできます。それほどugいものではありませんが、別のレベルの継承を意味します。
ピーターローリー

-2

JavaとC#の間で継承が処理される方法にまったく違いはありません。実際に継承またはコンポジションを使用する場合は、明確に設計上の決定であり、JavaやC#が推奨または推奨しないことは決してありません。この記事を読むことをお勧めします

私が助けたことを願っています!


5
言語自体について話しているのですが、質問はライブラリと一般的な使用法についてでもあると思います。
svick

3
しかし、そこにある Javaで余分な継承を促し、言語の残りの癖は、RalphChapinの回答
イズカタ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.