Javaの内部クラスの概念を見直しています。私が理解して適用したものとはかけ離れており、Java の内部クラスには、その外部/エンクロージング クラスのメソッドとフィールドへのリンクまたはアクセスがあります。
私の質問:
- 内部クラスをいつ作成または定義する必要がありますか?
- 内部クラスは「ヘルパー クラス」として呼び出されると見なされますか?
- 内部クラスを作成するための指標は何ですか?また、その他の目的は何ですか?
Javaの内部クラスの概念を見直しています。私が理解して適用したものとはかけ離れており、Java の内部クラスには、その外部/エンクロージング クラスのメソッドとフィールドへのリンクまたはアクセスがあります。
私の質問:
内部クラスは、1か所で使用されるクラスを論理的にグループ化するために最適です。たとえば、クラスを囲むだけで使用されるクラスを作成する場合、そのために別のファイルを作成することは意味がありません。代わりに、「内部クラス」として追加できます
Javaチュートリアルによると:
ネストされたクラスを使用する説得力のある理由は次のとおりです。
- これは、1か所でのみ使用されるクラスを論理的にグループ化する方法です。
- それはカプセル化を増加させます。
- それは、より読みやすく、保守しやすいコードにつながる可能性があります。
内部クラスの典型的な使用法は、コンテナー内のイテレーターの実装です(たとえば、 ArrayList -look for class Itr
)。コンテナが他の世界に公開したいのはすべてIterator
です。ただし、コンテナの内部に精通している可能性のある、そのイテレータの具体的な実装を作成する必要があります。内部クラスを使用すると、実装を非表示にし、コンテナの実装に近づけます。また、内部(つまり非静的)であるため、そのコンテナーの特定のインスタンスにバインドされ、プライベートコンテナーメンバーにアクセスできるようになります。
内部クラスには、非静的ネストクラス、ローカルクラス、匿名クラスなど、いくつかの種類があります。それぞれの目的は多少異なるため、内部クラスについて質問するときは、どの種類について話しているのかを指定する必要があります。
非静的内部クラスを参照していると仮定すると、それらを使用する理由は通常のクラスを使用するのと同じだと思います(つまり、コードを論理単位に抽象化して分割する)が、このクラスの使用を可視化する理由はありません世界の残りの部分に。もちろん、ネストされたクラスをパブリックにすることもできます。その場合、外部クラスとの緊密な関係を表現するために、独立ではなくネストされたクラスを作成します。
主な理由については、 Java チュートリアルを参照してください。
「ヘルパークラス」が内部使用のみを意味する場合は、必ずしもそうではありません。あなたは次のようなことをしたいかもしれません
class Outer {
private static class Inner implements InterestingInterface {
// whatever
}
public InterestingInterface make_something_interesting() {
return new Inner();
}
}
ここで、Inner
は、外部の世界がそのインスタンスを見ることができるという意味では「ヘルパー クラス」ではありませんが、その実装は完全に隠されていますInterestingInterface
。
原則として、オブジェクトは単一の責任のために設計する必要があります(非常にまとまりがあります)。言い換えれば、適切に設計されたオブジェクトは、単一の一貫したタスクを実行する必要があります。これは、オブジェクト指向設計のベスト プラクティスと見なされます。
ただし、開発者は、機能するために別の 特殊なクラスを必要とするクラスを設計する場合があります。この個別の特殊化されたクラスは、ヘルパー クラスと見なすことができます。
ヘルパークラスが他のクラスで使用されていない場合、内部クラスとして最有力候補と見なされます。
上記のncmathsadistによって引き出されたように、内部クラスの使用例はEvent handlersの実装にあります。
たとえば、グラフィカル ユーザー インターフェイス (GUI) を設計する際に、開発者は、ユーザーが押した後に特定のタスクを実行するボタンを作成している場合があります。
ボタンには、特定のボタンが押されたときにリッスンするイベント ハンドラーが必要です。
この場合、ボタンのイベント ハンドラを内部クラスとして作成するのがベスト プラクティスです。内部クラスは、GUI クラス内の特定のボタン以外では使用されないからです 。
内部クラスの目的の 1 つは、リスナーをアタッチすることです。たとえば、JMenuItem
. 次のコードに示すように、アプリを終了させることができます。
JMenuItem quitItem = new JMenuItem("Quit");
quitItem.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e)
{
//cleanup code before exiting
System.exit(0);
}
});
クラスが、そのクラスに完全に従属している外部クラスの状態変数にアクセスできるようにすることもできます。たとえば、単純な色計算機を作成することを検討してください。16 進コードを入力するテキスト領域がある場合があります。Enterキーを押すと、JPanelに色が表示されます。これは、あなたができることの大まかな概要です。
public class ColorCalc extends JPanel implements Runnable
{
Color displayedColor;
JTextArea colorEnterArea;
public ColorCalc()
{
displayedColor = Color.white
colorEnterArea = new JTextArea();
}
public void run()
{
//build GUI here
}
public static void main(String[] args)
{
ColorCalc cc = new ColorCalc();
javax.swing.SwingUtilities.invokeLater(cc);
}
//subservient inner class with access to outer class state variable.
class ColorPanel extends JPanel
{
public void paintComponent(Graphics g)
{
g.setColor(displayedColor);
g.fillRect(0,0,getWidth(), getHeight());
}
}
}
これはスタイルの問題です。内部クラスで実行できることは、一連の外部クラスとして実行することもできます。内部クラスは、軽量のクラスや外側のクラスに強くバインドされているクラスに特に役立ちます。たとえば、コンパレータは多くの場合、これらの両方です。クラスの実装に関する詳細な知識が必要であり、数行の長さしかない場合もあります。内部クラスとしては有力候補かもしれません。
クラスがフィールドとメソッドで統計と動作を指定するために提供するので、クラスによってより適切に実行できる十分なコードがあることがわかり、このクラスを囲んでいるクラスの外部で使用する必要がない場合。内部クラスを使用する必要があります。
ここでは、内部クラスが外部の世界から隠されています。内部クラスは、カプセル化を提供するエンクロージング クラスのプライベート メンバーにアクセスできます。
例を挙げましょう..ギアをサイクルに設定したい場合、最大6つのギアしかないというビジネスルールがあるとします。したがって、ギアを設定するメソッドを持つインナー クラス サイクルを作成できます。そのメソッドには、ギアを設定する前にチェックされるいくつかの検証があります。サイクルが実行されているように...ギア番号が6未満です...
最良の例は、イベント処理コードが内部クラス (場合によっては匿名内部クラス) を使用してイベントとリスナーを作成することです。イベント用に個別のイベント オブジェクト クラスとイベント リスナー クラスを作成する必要はありません。
これは単なる言語の特徴だと思います。OOD を採用し、SOLID の原則に従う場合は、使用しないことをお勧めします。