web-dev-qa-db-ja.com

Java開発は通常、C#/。NETよりも多くのサブクラス化を伴いますか?

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

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

C#では、ほとんどの状況で継承を回避できるように見えました。手元にあるタスクは通常、 。NET フレームワークの具象クラスを使用して実行できます。

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

これは、スタイルに煮詰めるには大きすぎる違いのようです。これの背後にある理由は何ですか?これを理解するまで、私はクリーンなJava=コードを書いていないように感じます。

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

または別の言い方をすると、

これら2つの言語の設計について、継承を多かれ少なかれ(奨励しているように)使用しているのは何ですか?

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

34
MetaFight

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

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

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

  1. .NETは、あまりにも多くの非ジェネリックコードが実装される前の、ライフタイムの早い段階でジェネリックを導入しました。別の方法は、タイプを特化するための多くの継承です。

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

31
Telastyn

これらは、特にこの分野では、非常に異なる言語です。クラスがあるとしましょう。この場合は、テキストボックスのようなユーザーコントロールにします。それを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に置き換えるので、必要はありません。クリーンコンパイルのためにメソッドを記述します。プログラムを正しく機能させるために必要なメソッドをオーバーライドするだけです。そのため、インターフェイスJava=で継承を使用して、C#のイベントで行ったことと一致させます。

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

Javaがこのように機能するのはなぜですか?柔軟性。whenSomethingHappensに渡されたオブジェクトは、どこかから完全にCleverPanelに渡された可能性があります。複数のCleverPanelインスタンスがUIControlのように渡す必要があるかもしれません。 CleverWindowオブジェクトを支援するオブジェクトOrUIControlはそれをitsコンポーネント。

さらに、アダプターの代わりに、何千行ものコードが背後にあるDoSomething実装がどこかにあるかもしれません。 thatの新しいインスタンスを作成して渡すことができます。 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での継承の容易さ。)

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

6
RalphChapin