JAvaベースのマルチステート


以下は、この例について主に分析するマルチステートの例です.
package javaDemo.unit8;

import java.io.ObjectInputStream.GetField;

class Glyph{
	int field1 = 1;
	static int field2 =2;
	public String getField(){
		return "Glyph: field1 = " + field1 + ", field2 = " + field2;
	}
	void draw(){
		System.out.println("Glyph.draw()");
	}
	static void info(){
		System.out.println("Glyph.static info()");
	}
	Glyph(){
		System.out.println("Glyph() before info()");
		info();
		System.out.println("Glyph() after info()");
		System.out.println("Glyph() before draw()");
		draw();
		System.out.println("Glyph() after draw()");
	}
}

class RoundGlyph extends Glyph{
	int field1 = 3;
	static int field2  = 4;
	private int radius = 1;
	public String getField(){
		return "RoundGlyph: field1 = " + field1 + ", filed2 = " + field2;
	}
	public String getSuperField(){
		return "SuperFiled: field1 = " + super.field1 + ", filed2 = " + field2;
	}
	
	public RoundGlyph(int r) {
		radius = r;
		System.out.println("RoundGlyph.RoundGlyph(), radius = " + radius);
	}
	void draw(){
		System.out.println("RoundGlyph.draw(), radius = " + radius);
	}
	static void info(){
		System.out.println("RoundGlyph.info()");
	}
}

public class PolyConstructors {
	public static void main(String[] args) {
		Glyph g = new RoundGlyph(7);
		g.draw();
		g.info();
		System.out.println("g.field1 = " + g.field1 + ", g.field2 = " + g.field2);
		System.out.println(g.getField());
		
	}
}

出力は次のとおりです.
Glyph() before info()Glyph.static info()Glyph() after info()Glyph() before draw()RoundGlyph.draw(), radius = 0Glyph() after draw()RoundGlyph.RoundGlyph(), radius = 7RoundGlyph.draw(), radius = 7Glyph.static info()g.field1 = 1, g.field2 =  2RoundGlyph: field1 = 3, filed2 = 4
以前のマルチステート学習により、最下位の出力を簡単に分析できます.
①RoundGlyph: field1 = 3, filed2 = 4
これはJavaではstaticメソッドとfinalメソッド(privateメソッドもfinalメソッドに属する)以外のすべてのメソッドが動的にバインドされているためである.
≪バインド|Bind|emdw≫:同じメソッド・ボディを呼び出すメソッドを関連付けます.
バインドは、前期バインドと動的バインド(後期バインド、実行時バインド)に分けられます.
前期バインド:プログラム実行前にバインド
≪後期バインド|Post Binding|emdw≫:実行時にオブジェクトのタイプに基づいてバインドされます.
 
出力に対して
②g.field1 = 1, g.field2 =  2
これはfiledへのアクセス操作は,コンパイラによって解析され,マルチステートではないためである.したがって、親のfieldの値を直接出力します.
実際の開発では、filedをprivateに設定し、getメソッドで値を取得するので、サブクラスのfieldの値を取得します.サブクラスとベースクラスのfieldに同じ名前を設定しないでください.
③初期化を行うと,ベースクラスのコンストラクタが最初に呼び出されることが分かる.
これは、エクスポートクラスは一般的に自分のメンバーにしかアクセスできず、ベースクラスのメンバーにアクセスできず、ベースクラスのコンストラクタだけが自分の要素の初期化を適切に完了できるためです.また、サブクラスは、ベースクラスのpublicおよびprotectedメンバーにアクセスしてサブクラスの初期化を完了することができるため、すべてのコンストラクタが呼び出されてこそ、完全なオブジェクトが構築され、サブクラスオブジェクトが直接または間接のすべての親から継承されたインスタンス変数が正しく初期化されることを保証することができます.

Glyph() before info()Glyph.static info()Glyph() after info()
info()は、staticメソッドに前期バインドされているため、ベースクラスのメソッドが呼び出されます.

Glyph() before draw()RoundGlyph.draw(), radius = 0Glyph() after draw()RoundGlyph.RoundGlyph(), radius = 7
サブクラスの初期化時に親クラス構築メソッドが実行される場合でも、構築メソッド内のメソッドは動的にバインドされていることがわかります.
初期化の順序を分析します.
1)最初に,オブジェクトに割り当てられた記憶領域をバイナリのゼロに初期化する.
2)初期化されたクラスに親が存在する場合、親の構築メソッドが呼び出され、構築メソッド内のメソッド呼び出しは動的呼び出しのルールに従う(初期化クラスの構築メソッドはまだ呼び出されていないのでradiusの値は0).
3)メンバーの初期化メソッドを宣言された順序で呼び出す.
4)初期化クラスの構築方法を呼び出す.
これは、できるだけ簡単な方法でオブジェクトを正常な状態にしなければならないことを示唆しています.他のメソッドの呼び出しはできるだけ避けます.構築メソッド内で安全に呼び出すことができるメソッドは、ベースクラスのfinalメソッド(またはprivateメソッド)である.