4

だから私はJavaでデータ構造の視覚化を作成することに取り組んでいます。開始するデータ構造 (二分探索木) の実装は既にありますが、含まれているノード クラスにいくつかの追加機能を追加する必要があります。規則とベスト プラクティスに関する限り、この追加機能を使用してノードのサブクラスを作成する必要がありますか?それとも、持っているものを変更してそこに文書化する必要がありますか?

私の質問はここで尋ねられたことと似ていますが、それは私の頭を少し超えています。

私がやっていることにはあまり関係がないことはわかっているので、一般的なこととして質問しています。

編集:おそらくもっと明確にすべきだったでしょう。私の変更は、いくつかの余分なフィールド (x 座標と y 座標に加えて、そのノードが強調表示されているかどうかを設定するブール値) とそれらのフィールドにアクセス/変更する関数を追加する以外は、実際には元の実装を変更しません。また、私が取り組んでいるノード クラスは BST 実装に含まれています。

あなたの答えを読むと、どちらの場合にも議論が行われるようです。一般的には、別のクラスまたはインターフェイスを作成することがおそらく最善の方法であることに同意します。ノードからデータを抽出する方法がまだ必要なため、別のクラスを作成するのは難しいようです。私が使用している BST 実装は汎用的であり、データを返すだけの Node クラスまたは BST クラス自体にそのような機能がないため、少なくとも追加する必要があります。

有益な回答をありがとう。

4

5 に答える 5

12

答えるべき質問は、データ構造を視覚化していないとき、「基本機能」は便利ですか、望ましくないですか?

クラスをまったく拡張したくない場合もあります。詳細がなくても、機能するデータ構造があるように思えます。それを視覚化する方法を知っている新しいクラスを作成できます。

つまり、それ自体を視覚化する方法を知っているデータ構造の代わりに、データ構造と、データ構造を視覚化する方法を知っている別のクラスがあります。一体-キュー、スタックなどを視覚化する必要があるかもしれないので、それが別のクラス階層全体に進化することに気付くかもしれません。バイナリ検索ツリーでは何もしません。

于 2010-04-28T16:25:15.217 に答える
3

あなたは一般的に尋ねているので、ここに短い答えがあります.それは本当に状況に依存します.

まず、サブクラスは親クラスと「IS-A」関係にあると見なされます。新しいサブクラスが元のクラスの特定の種類であると言えない場合は、間違った質問をしているので、無関係な新しいクラスを作成する必要があります。

  • 新しいコードがクラスの中心的な目的に密接に関連しており、クラスのすべてのメンバー (たとえば、すべての BST) に適用される場合は、変更したほうがよい場合があります。結束力が高いのがいい。
  • 新しいコードがクラスの中心的な目的に関連しているが、そのタイプの一部のオブジェクトのみ (たとえば、バランスのとれた BST のみ) と関係がある場合は、おそらくサブクラス化が最適です。
  • 変更内容、コードが使用されている場所の数、コードを使用しているさまざまな人/組織の数などによっては、変更によって他のコードで予期しない動作が発生する可能性があるため、既存のコードを変更する前によく考えてください。これは、一般的に使用されるものを自動的にサブクラス化するという意味ではありません。上記の理由から、それはしばしば間違っています。

あなたの特定のケースでは、n8wrl に同意します。視覚化はデータ構造とは何の関係もないため、サブクラスVisualizableを作成するよりも、完全に別のインターフェイスを実装する方がよいでしょう。DrawableBSTNode

于 2010-04-28T16:57:42.390 に答える
2

既存の実装に機能を追加する一般的なケースでは、既存の実装を変更するのではなく、拡張する必要があります。

そして、これが私の推論です。そのノードがバイナリ サーチ ツリーの実装以外の場所で使用されている場合は、それを変更するときに、使用されているすべての場所を見つけて、それらの場所が変更と競合しないようにする必要があります。通常、新しいメソッドの形で機能を追加するだけでは問題は発生しませんが、問題が発生する可能性があります。オブジェクトがどのように使用されるかはわかりません。

2 つ目は、Binary Search Tree でのみ使用される場合でも、BST の実装が変更で適切に動作することを確認する必要があります。

最後に、拡張する場合は、ポイント 1 と 2 について心配する必要はありません。また、変更を元の実装とは常に分けておくという追加のボーナスも得られます。これにより、自分が行ったことを追跡してコメントすることが容易になります。

于 2010-04-28T16:22:30.967 に答える
2

簡単な答えはありません。いつ、どのように機能を追加するかを知ることは、時間をかけて学ばなければならないことです。

基本クラスに追加するだけで簡単な解決策のように思えますが、それは基本クラスを汚染しています。これが別のプログラム (またはプログラムの一部) が使用することを合理的に期待できるクラスである場合、追加する機能はクラスの責任のコンテキストで意味がありますか? そうでない場合、これはおそらく悪い動きです。基本クラスを特定の用途にリンクする依存関係を追加していますか? もしそうなら、それはコードの再利用を窓の外に投げ出しているからです。

継承は、多くのエンジニアが引き寄せられるソリューションであり、魅惑的な方法です。しかし、私がエンジニアとして成長したので、控えめに使用するものです。継承は、真の is-a 関係でのみ使用する必要があり、行動のサブタイプを尊重する必要があります 。そうしないと、後で後悔することになります。また、Java では単一の継承しか許可されていないため、サブタイピングは 1 回しかできません。

コンポジション (特にインターフェースを使用) は、多くの場合、より良いアイデアです。is-a 関係のように見えるものは、実際には has-a 関係であることがよくあります。または、元のクラスを引数として取る多くの関数を持つヘルパー クラスだけが本当に必要な場合もあります。

ただし、構成には 1 つの問題があります。これらのオブジェクトをツリーに格納する必要があります。ここでの解決策はインターフェースです。ノードを格納するツリーは必要ありません。ノードを提供できるインターフェイスを持つオブジェクトが必要です。

public interface HasNode {
    public Node getNode();
}

あなたのノードクラスは、 getNode がこれを返すだけの HasNode です。NodeVisualizer クラスも HasNode であるため、NodeVisualizer をツリーにも格納できるようになりました。もちろん、別の問題があります。ツリーに NodeVisualizers と Nodes が含まれている可能性がありますが、それは良くありません。さらに、ツリー関数から HasNode を取得するときに、それらを適切なインスタンスにキャストする必要があり、それは醜いです。そのためにテンプレートを使用したいと思うでしょうが、それは別の答えです。

于 2010-04-28T21:21:06.933 に答える
0

論理的に独立した機能を混同すると、混乱が生じます。サブクラス化は非常に特殊な関係であり、しばしば過度に使用されます。サブクラス化は Is-a-Kind 関係用です。

何かを視覚化したい場合は、そのために完全に独立したクラスを作成してみませんか? Node オブジェクトをこれに渡すだけです。(または、さらに良いことに、インターフェイスを使用します。)

于 2010-04-28T18:38:56.467 に答える