Javaベースの再実行:オブジェクト向け-マルチステートとその一般的な問題

9120 ワード

一、多態の概要
マルチステートは、カプセル化、継承に続いてオブジェクトに向かう3番目の特性です.
現実の物事はいつも多種の形態を体現することができて、例えば学生、学生は人の1種で、1つの具体的な同級生の張三は学生でも人でもあり、つまり2つの形態が現れます.
Javaはオブジェクト向けの言語として,同じように一つの物事の多様な形態を記述することができる.StudentクラスがPersonクラスを継承している場合、1つのStudentのオブジェクトはStudentであり、Personでもあります.
Javaにおけるマルチステートのコードは、1つのサブクラスオブジェクト(実装クラスオブジェクト)がこのサブクラス(実装クラスオブジェクト)に変数付与を参照することもできるし、このサブクラス(実装クラスオブジェクト)の親(インタフェース)変数に付与することもできる.
例えば、StudentクラスはPersonクラスのサブクラスであってもよい.では、Studentオブジェクトは、Studentタイプの参照に値を付けることも、Personタイプの参照に値を付けることもできます.
最終的なマルチステートは、親参照変数がサブクラスオブジェクトを指すことができるように表現されます.
注意:
1.マルチステートの前提は、子の親またはクラスがインタフェース関係を実現しなければならないことです.そうしないと、マルチステートを完了できません.2.マルチステート後の親参照変数呼び出しメソッドを使用すると、サブクラス書き換えメソッドが呼び出されます.
二、多態の3種類の定義と使用フォーマット
汎用フォーマット:
          = new     ();  		//    
   .   ();  						//    


1.一般クラスマルチステート定義のフォーマット
       = new   ();
 :	class Fu {}
	class Zi extends Fu {}
	//      
Fu f = new Zi();


2.抽象クラスマルチステート定義のフォーマット
        = new      ();  
 :	abstract class Fu {
         public abstract void method();
	     }
class Zi extends Fu {
public void method(){
		      System.out.println(“        ”);
}
}
//      
Fu fu= new Zi();


3.インタフェースのマルチステート定義のフォーマット
       = new      ();
 : interface Fu {
		     public abstract void method();
}
class Zi implements Fu {
		     public void method(){
              System.out.println(“        ”);
}
}
//       
Fu fu = new Zi();


注意事項
同じ親のメソッドは、異なる子に書き換えられます.メソッドを呼び出すときに呼び出されるのは、各サブクラスに書き換えられたメソッドです.
  Person p1 = new Student();
   Person p2 = new Teacher();
   p1.work(); //p1   Student     work  
   p2.work(); //p2   Teacher     work  


したがって、変数名が異なるサブクラスオブジェクトを指す場合、各サブクラスの書き換え親メソッドの内容が異なるため、異なるメソッドが呼び出されます.
三、マルチステート——メンバーフィーチャー(メソッドと変数呼び出しフィーチャー)
1.メンバー変数の呼び出しフィーチャー
マルチステートの定義を行うと、マルチステートが現れるとクラスのメンバーはどのように変化しますか?継承時に子親クラス間のメンバー変数に独自の特定の変化があることを知っていますが、マルチステートが現れると、メンバー変数の使用に変化はありませんか?
まず、メンバー変数の変化を見てみましょう.
出力結果を考えるとなぜ?
class Fu {
	int num = 4;
}
class Zi extends Fu {
	int num = 5;
}
class Demo {
	public static void main(String[] args) 	{
		Fu f = new Zi();
		System.out.println(f.num);
		Zi z = new Zi();
		System.out.println(z.num);
	}
}


出力結果:
4    //            
5    //         ,           

コードの変化に注意して、コードの出力結果を考えてみましょう.
class Fu {
	//int num = 4;    -----------         
}
class Zi extends Fu {
	int num = 5;
}
class Demo {
	public static void main(String[] args) 	{
		Fu f = new Zi();
		System.out.println(f.num);   // ---------f.num      
		Zi z = new Zi();
		System.out.println(z.num);
	}
}

実は以上のコードはコンパイルできません.試してみてください.私はこれでスクリーンショットをしません.
ポイント:
そのため、以下の法則をまとめることができます.
マルチステートがメンバー変数を呼び出した場合:
  • コンパイル期間:参照タイプ変数が属するクラスに呼び出されるメンバー変数があるかどうか.あります.コンパイルによって、運行時期に入ります.いいえ、コンパイルに失敗しました.
  • ランタイム:参照タイプ変数が属するクラスのメンバー変数を直接呼び出します.

  • 簡単:コンパイルと実行は、等号の左側を参照します.コンパイル実行は左を見てください.つまり、親の顔色を見て行動すると、親にはこの変数があり、親メンバー変数を直接呼び出し、親にはなく、コンパイルにはパスできません.マルチステートの呼び出しは、サブクラスのメンバーの有無に関係ありません.
    2.メンバーメソッドの呼び出しフィーチャー
    マルチステート呼び出しでは、同調用メンバー変数が似ており、マルチステートが現れると、子親クラスのメンバーメソッドもわずかに変化します.
    出力結果を考える?
    class Fu {                                   //      
    	int num = 4;
    	void show()	{                  //          
    		System.out.println("Fu show num");
    	}
    }
    class Zi extends Fu {              //      ,      
    	int num = 5;
    	void show()	{             //       show  
    		System.out.println("Zi show num");
    	}
    }
    class Demo {                       //   
    	public static void main(String[] args) 	{
    		Fu f = new Zi();
    		f.show();            //      ?
    	}
    }
    
    

    出力結果:
    Zi show num                   //             
    

    コードの変化に注意!
    class Fu {
    	int num = 4;
    	/*
    	void show()	{
    		System.out.println("Fu show num");
    	}
    	*/
    }
    class Zi extends Fu {
    	int num = 5;
    	void show()	{
    		System.out.println("Zi show num");
    	}
    }
    class Demo {
    	public static void main(String[] args) 	{
    		Fu f = new Zi();
    		f.show();     //       :   Fu   show  ,      
    	}
    }
    

    **出力結果は何ですか?**同様に、コンパイルに失敗しました.みんな自分でやってみよう.
    ポイント:
    そのため、以下の法則をまとめることができます.
    マルチステートがメンバーメソッドを呼び出す場合:
  • コンパイル期間:参照変数が属するクラスを参照し、クラスに呼び出しのメソッドがない場合、コンパイルに失敗します.ある場合は運転時期に入ります.
  • 実行期間:非静的メソッドの場合、参照変数が指すオブジェクトが属するクラスを参照し、オブジェクトが属するクラスのメンバーメソッドを実行し、オブジェクトが属するクラスに親メソッドが書き換えられていない場合、親メソッドの呼び出しメソッドを実行します.ただし、静的メソッドが呼び出された場合、参照変数が属するクラス(親クラス)の静的メソッドが実行され、子クラスには関係ありません.
  • コンパイルは左を見て、実行は右を見てください.つまり、親クラスに非静的メンバーメソッドがあり、
    1.子クラスが親クラスのメンバーメソッドを書き換えると、子クラスのメンバーメソッドが直接呼び出されます.2.子クラスが親のメンバーメソッドを書き換えていない場合は、親クラスのメンバーメソッドを直接呼び出します.
    ;親クラスにこの非静的メンバーメソッドがない場合、子クラスにメンバーメソッドが含まれていてもコンパイルは通過しません.静的メソッドが呼び出されている場合は、子クラスに関係なく、親クラスの今日のメソッドが直接呼び出されます.
    マルチステート呼び出しのメンバーフィーチャーの概要
  • メンバー変数:
  • コンパイルの場合、参照親にこの変数があるかどうか、ある場合はコンパイルに成功し、コンパイルに失敗しません
  • が実行するとき、実行するのは親の変数値
  • です.
  • コンパイル実行全参照親
  • メンバーメソッド:
  • コンパイルの場合、参照親にこの方法があるかどうか、ある場合、コンパイルに成功し、コンパイルに失敗しなかった
  • 運転の場合、運転時にメソッドタイプを見ます.非静的メソッドの場合、サブクラスの書き換えメソッドが実行されます.静的メソッドの場合、子クラスに関係なく親クラスの静的メソッドが実行されます.
  • 親クラスをコンパイルし、呼び出しを実行するメソッドタイプ
  • 四、多態のタイプ判別問題(instanceofキーワード)
    マルチステートによる問題:参照タイプの実際のオブジェクトタイプの疑問問題
    次のコードを見てください:考えます!
    public abstract class Person {      //        Person  
    	public abstract void sleep();
    }
    
    public class Student extends Person {   //      Student   
    	public void sleep(){
    		System.out.println("       ");
    	}
    	public void study(){
    	}
    }
    
    public class Teacher extends Person{    //         Teacher  
    	public void sleep(){
    		System.out.println("     ");
    	}
    }
    

    次に、このようなテストクラスを見てみましょう.
    public class Test {
    	public static void main(String[] args) {
    		Person p1 = new Student();
    		Person p2 = new Teacher();
    	}
    }
    

    考えてみましょう.Person p1 = new Student();Person p2 = new Teacher();は、マルチステートの生成により、この2つの参照変数の参照された実際のオブジェクトタイプをどのように分解するかについて、Javaではinstanceofキーワードを使用して参照タイプが指すオブジェクトの実際のタイプを判断します.キーワードを使用してオブジェクトの実際のタイプを判断し、対応するメソッドを呼び出すことができます.
    public class Test {
    	public static void main(String[] args) {
    		Person p1 = new Student();
    		Person p = new Teacher();
    		
    		if(boolean b = p instanceof Student){
    			System.out.println(b);
    			p.sleep();
    		}
    		if(boolean b = p instanceof Teacher){
    			System.out.println(b);
    			p.sleep();
    		}
    	}
    }
    

    五、多態——転換問題
    実際には、マルチステート定義の過程で、データの転換の問題に関連しています.マルチステートの定義フォーマットが親変数の参照としてサブクラスのオブジェクトを指すことを知っています. = new ();です.ここでは、ベースデータ型と同様に、データの移行問題に関連しています.
    多態の転換は上向きの転換と下向きの転換の2種類に分けられる.
    1.アップシフト:子オブジェクトが親参照に付与されると、アップシフトし、マルチステート自体がアップシフトするプロセスです.
  • 使用形式:
  •           = new     ();
     :Person p = new Student();
    

    上への転換は理解しやすいので、次は別の転換について話します.
    2.ダウンシフト
    背景:なぜ下への転換が必要なのか.まじめに見て!
    マルチステート呼び出しメンバーメソッドと変数について前に述べた.メンバー・メソッドを呼び出すと、親にメンバー・メソッドが含まれており、メソッドがクラスによって書き換えられた場合、サブクラス書き換えメソッドが呼び出されますが、親にメソッドがない場合はコンパイルできません.呼び出しメンバー変数の場合、コンパイルまたは実行は、子クラスに関係なく、親クラスのメンバー変数に基づいてコンパイルおよび実行されます.
    サブクラスの独自のメソッドまたはメンバー変数を呼び出す必要がある場合、呼び出すメソッドまたはメンバー変数はサブクラス固有ですか?どうやって実現すればいいのでしょうか?次のコードがあります.
    public abstract class Person {      //        Person  
    	int i =10 ;
    	public abstract void sleep();
    }
    
    public class Student extends Person {   //      Student   
    	String name = "    ";
    	public void sleep(){
    		System.out.println("       ");
    	}
    	public void study(){	
    		System.out.println("     java");
    	}
    }
    

    マルチステート呼び出しサブクラスstudy()メソッドをどのように利用しますか?次に、次のコードを見ます.
    public class Test {
    	public static void main(String[] args) {
    		Person p = new Student();
    		p.sleep();  //        Student sleep()  
    		//p.study();                    !
    		//            
    		Student s = (Student) p;
    		p.study(); //        
    		p.name;
    	}
    }
    

    定義:アップコンバートされたサブクラスオブジェクトは、強制タイプ変換のフォーマットを使用して、親参照をサブクラス参照に変換できます.このプロセスは、ダウンコンバートです.親オブジェクトを直接作成する場合は、下に移動できません.
  • 使用形式:
  •              = (    )        ;
         :Student stu = (Student) p;  //  p      Student  
    

    まとめ:サブクラス固有のメンバー変数とメソッドを呼び出すには、ダウンシフトを使用します.
    多態転換の通俗理解(孔子はお父さんを装う)、よく理解してください!
    私たちは2つのクラスを定義します.1つは孔子のお父さんです.一つは孔子類
    public class      {
    	int    =  80 ;
    	public void   (){
    	System.out.println("        ,   ")
    	}
    } 
    
    public class    {
    	int    = 48 ;
    	public void    ()
    	System.out.println("      ,    ")
    	}
    } 
    

    もしある日孔子の隣人が孔子のお父さんに豚を殺すように頼んだとしたら、孔子のお父さんは出張して家にいないで、前に承諾したので、古人は誠実さにこだわって、そのため孔子はお父さんを装って隣人の豚を殺すようにして、しかし彼は隣人が認識することを恐れて、彼は仮装して、彼の隣人の豚を殺すように手伝いました.豚を殺した後、彼は化粧を落として学院に行って学生に授業をした.次は多態の過程で孔子の一日の仕事を実現します!
    public class      {
    	//       
    	//     :
    	      fakeDade = new   ();  //        ,   
    	//     : 
    	 fakeDade.  ();//     
    	//       
    	//      :
    	  trueSon = (  )fakeDade; //        ,    
    	//     
    	 trueSon.   (); //     ,