🦄
【Java】変数の継承関係
色々の要素を組み合わせて検証
static変数、通常変数、staticメソッド内外のsuper、直接呼び出し、インスタンス化呼び出し、メンバ変数、ローカル変数
検証観点
考察の起点として以下がありました。
「変数ってオーバーライドするの?」
結果
「変数ってオーバーライドするの?」
これを起点に考えた場合に色々な疑問が浮かびました。
・static変数の場合は?
・通常変数だったら?
・staticメソッド内のsuper?
・staticじゃないメソッドでsuperなら?
・直接呼び出した場合は?
・インスタンス化して呼び出しだら?
・メンバ変数だったらどうだろ?
・ローカル変数なら動くかな?
結果オーバーライドという概念ではないようでした。
ただ色々実行していくうちに変数の継承関係について理解することができました。
あっちをこうしたらどうなるんだろ?
とか
こっちをこれに変えたらどうゆう動きになるんだろ?
とか
楽しかったです。
だいぶヒッチャカメッチャカですがw
つまみ程度に使っていただけたらと思いアップしました。
なにか参考になっていただけたら嬉しいです。
理解するキッカケだけちょーだい
とか
こっちで編集するし何かなんでもいいからコピペってポチポチってできるヤツちょーだい
とか
そんか感じだったら、もしかしたら丁度よいかも?
実験
コードをDokojavaに貼り付けると実行テストできます。
このマークです↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// ファイル名
// Main.java
class A{
//■■■■■■■■■■■■■■■ 変数のオーバーライドテスト ■■■■■■■■■■■■■■■//
static int instanceVarOverrideTest0 = 99 ;
int instanceVarOverrideTest1 = 3 ;
int instanceVarOverrideTest2 = 8 ;
static int num = 1 ;
A(){
num = num+3;
}
}
class B extends A {
//■■■■■■■■■■■■■■■ 変数のオーバーライドテスト ■■■■■■■■■■■■■■■//
static int instanceVarOverrideTest0 = 7 ;
int instanceVarOverrideTest1 = 5 ;
// instanceVarOverrideTest2 = 9 ; //継承した変数をメンバ変数で使うことはできない
// super.instanceVarOverrideTest2 = 9 ; //継承した変数をメンバ変数でsuper指定でも使うことはできない
void myPrint(){
System.out.println(instanceVarOverrideTest1 + " ←継承先で宣言しなおした変数をインスタンス化したメソッド経由で出力");
System.out.println(super.instanceVarOverrideTest1 + " ←継承先で宣言しなおした変数をインスタンス化したメソッド経由で明示的にスーパークラスを呼び出して出力");
instanceVarOverrideTest2++; //継承した変数をローカル変数で使うことはできる
System.out.println(instanceVarOverrideTest2 + " ←継承した変数をローカル変数で利用"); //継承した変数をローカル変数で使うことはできる
}
//変数はオーバーライドしない、オーバーライドはメソッドだけ
//継承はするけどね、って話し?
// num = 10 ;
static int numb = 10 ;
int num2 = 3 ;
B(){
// num = 10 ;
// num++;
numb++;
num2++;
}
}
class Main extends B{
void aaaaa(){
System.out.println(instanceVarOverrideTest0 + " ※以下の比較用(super指定なし)");
System.out.println(super.instanceVarOverrideTest0 + " ※super指定したいがためにstaticじゃないメソッドを用意(インスタンス化用)");
// System.out.println(super.super.instanceVarOverrideTest0 + " ※super指定したいがためにstaticじゃないメソッドを用意(インスタンス化用)"); //更に上の継承クラスを呼び出すことはできない
}
public static void main (String[] args){
//■■■■■■■■■■■■■■■ 変数のオーバーライドテスト ■■■■■■■■■■■■■■■//
Main e1 = new Main();
e1.aaaaa();
System.out.println(B.instanceVarOverrideTest0 + " ←staticだからインスタンス化しないで直接呼び出せる(元々領域確保しているため) ※サブクラスの変数呼び出し");
System.out.println(A.instanceVarOverrideTest0 + " ←staticだからインスタンス化しないで直接呼び出せる(元々領域確保しているため) ※スーパークラスの変数呼び出し");
System.out.println(instanceVarOverrideTest0 + " ←staticだからインスタンス化しないで直接呼び出せる(元々領域確保しているため)"); //このクラスでも継承すれば呼び出せる
B e = new B() ; //インスタンス化(オブジェクト作成)
System.out.println(e.instanceVarOverrideTest1 + " ←継承先で宣言しなおした変数");
System.out.println(e.instanceVarOverrideTest2 + " ←継承先で宣言しなおしてない変数(継承元のままの変数)");
// System.out.println(e.super.instanceVarOverrideTest1 + " ←継承先で宣言しなおした変数じゃなくて明示的にスーパークラスを呼び出す"); //コンパイルエラー
e.myPrint();
//オーバーライドというか、ただの宣言しなおしか?
B b1 = new B();
B b2 = new B();
B b3 = new B();
//B型(コンストラクタB)の配列変数valBか
B[] valB = {b1,b2,b3};
//拡張for文(foreach) for(配列と同じ型の変数宣言 : 配列)
for(B obj : valB ){
// System.out.print(obj.num + " " + " ");
System.out.print(obj.numb + " " + " ");
System.out.print(obj.num2 + " ←継承元をstaticにすると実行毎加算(継承元の隠れsuper();含め計5回実行されるため5プラス)");
System.out.print("\n");
}
//numってオーバーライドしてるのか?→オーバーライドしてない
System.out.println(B.num + " ←隠れsuper();が継承元で5回実行されている。(最初のメソッドが勝手に5回)");
}
}
//■■■■■■■■■■■■■■■ 変数のオーバーライドテスト結果 ■■■■■■■■■■■■■■■//
//結論:オーバーライドという概念ではない。オブジェクト指向がもろにでてるのか、、、
//・継承先クラス
// メンバ変数
// 継承した変数は利用→不可 ※宣言しなおしは可能(ただ新しく同名で宣言してるだけ)
// superで明示的に呼び出す→不可(同上)
// ローカル変数
// 継承した変数を利用→可能
// superで明示的に呼び出す→可能
//・実行クラス(Main)
// superで明示的に呼び出す
// staticメソッド内→不可(バグ回避と思われる[領域一つにsuperを直接呼び出すわけだから領域未確保を呼び出されても困る])
// staticじゃないメソッド内→可能
// 直接呼び出す→可能(ローカル変数として呼び出してるから可能、そもそもローカル変数では利用可能なため)
Discussion