🔥

プログラミング自主学習 DAY55 ネストクラス

2023/07/21に公開

ネストクラス(Nested Class)

特定なクラスが一か所しか使われない場合、
そのクラスを、他のクラス内部に宣言します。

それをネストクラスと呼びます。

クラスのメンバーとして、宣言されたメンバークラス、
メソッド内部に宣言されたローカルクラスがあります。


https://sjh836.tistory.com/145

なぜネストクラスを組むか?

  • クラス間の上下関係をわかりやすく表すためだ。
  • カプセル化のためだ。
  • 読みやすくなり、メインテナンスが簡単になるためだ。

メンバークラス

メンバーインスタンスクラス(Non-static Inner Class)

[public] class Outer{
     [public][private]class Inner{
     }
}

インスタンスクラスは、主にprivateクラスだ。
private の場合、Class Outer内部でしか使用できない。

戦いで相手の技と技術を知れば、不利になるように
内部にあるインスタンスクラスを private にすることで内部の情報を隠す。

インスタンスクラスのオブジェクトを生成するためには、外部クラスのオブジェクトを生成することか必修だ。

また、継承したクラスと異なり、外部クラスのオブジェクトの中にあるクラスでるため、
外部クラスのフィールドを使用することもできる。

OuterWizardInnerFantasy

public class Wizard {
	
    private int mp=0;
    
private class Fantasy{
		
    public void showFantasyStar(){
	System.out.println("****************");
	}
  	
  public void fantasyPower(){
	  mp = 100;
	  System.out.println("mp: " + mp);
	} 	
		
   }
	
	
String name;
	
   Wizard(String name){
	  this.name = name;
	  System.out.println("魔法使い "+ name + "を生成しました。");
	}
	
	
public void showFanatasy() {
	if(mp>90){
	Fantasy a = new Fantasy();
	System.out.println("$$$$$$$$$$$$$$$$");
	a.showFantasyStar();
	mp = 0;
	System.out.println("幻覚が消えました。");
	}
	}

}


RPG
public class RPG {

public static void main(String[] args) {
		
	    Wizard wiz = new Wizard("Harry Potter");
	    
	    System.out.println();
	    
	    wiz.fantasyPower();
	    wiz.showFanatasy();

	}

}

魔法使い Harry Potterを生成しました。

mp: 100
$$$$$$$$$$$$$$$$
****************
幻覚が消えました。

メンバー静的クラス(Static Inner Class, Static Nested Class)

[public] class Outer{
     [public][default]static class Inner{
     }
}

staticを付けることで、class Outer のメンバーになるため、外部では、Outer class のオブジェクトを生成せずに、Class Inner を使用することができる。
その目的で主に、メンバー静的クラスのアクセス修飾子は主には、public と default を使う。

ローカルクラス(Method Local Inner Class)

[public] class Outer{

      public Outer(){
         class Local{}  //default
      }
      
      public void method(){
        class Local{}   //default
      }
}

メンバークラスと比べ、クラスにアクセス修飾子とstaticを付けることができない。
外部では、オブジェクトの生成もフィールドとメソッドを使用することすらできないためだ。

実務では、非同期処理のためにスレッドのオブジェクトを生成するために使われるようだ。

LocalClass
public class Outer {
	
     void useLocal() {
	//Local Class
	class Local {
		   
	    int field1 = 1;	
	    static int field2 = 2;
		   
             Local(){
		System.out.println("Local Constructor excuted");
	       }
		   
		  
              void method1() {
		System.out.println("Local-method1 excuted");
	      }
		   
		   
              static void method2() {
	           System.out.println("Local-method2 excuted");
		 }
             }	

	  }
     }

LocalExample
public class AExample {
	public static void main(String[] args) {
		
		Outer o = new Outer();
		
		o.useLocal()();

	}

}

Local Constructor excuted
Local-method1 excuted
Local-method2 excuted


また、メソッドを呼び出した後、消えるため、ローカルクラスの変数は実質的にfinalと似ている。(Java 7以前はfinalを付けることが必修だったが、今は明示的に付ける必要はない。

LocalFinal

public class A {
	
  public void method1(int arg) { //final int arg
	  
	  int var = 1;              //final int var
	  
	  class B{
		  
		  void method2() {
			  System.out.println(arg);
			  System.out.println(var);
			  
			  //arg = 2;  compile error   
			  //var = 2;  compile error
			  
		  }
	  }
	  
	  B b = new B();
	  b.method2();
	  
	  //arg = 3; compile error
	  //var = 3; compile error
	  
  }

}

this vs .this

class Outer{

    class Inner{

class B{

    class A{

メンバークラスのオブジェクトが自分のフィールド、メソッドを使用させるためには this を作成し、外部クラスのフィールドとメソッドに接近させるためには
外部クラスの名前の後に .this を付ける。

outer.this
A.this

Discussion