いやはや どうもどうも 権蔵です。
昨日は暑かったですねえ。
クーラーの設定温度をかなり下げないと生きた心地がしなかったです。
屋外で仕事をされている方、熱中症対策、滞りなく!
Java
プログラミング言語の中でも、それなりに長生きしている言語で、Java言語というのがあります。ジャヴァと読みます。スターウォーズに出てくるジャバザハットにゆかりがあるのかどうか、そこは知りまへん。
個人的には、好きな言語の一つですよと。
クラゲに刺される
そんなJava言語に、久々に刺されました。プログラムを書いていて、自分の想定する動きとかい離する動きをし始めたわけです。「はれれ??」状態で中身を見てたんですけどね。
まずはこちらのコードをご覧くださいまし。
public abstract class BaseClass { public BassClass() { init(); } public abstract void init(); }
なんの変哲もないコードです。abstract Classで、init()という(純粋)仮想関数作りましたよーだけです。
public Class SampleA extends BassClass { public int a = 10; //デフォルト値 @Override public void init() { a = 20;//値を上書き } }
そのクラスの上に、こんなクラスを実装しましたよーと。
そして、
public Class MainSample { public static void main( String[] args ) { SampleA data = new SampleA(); System.out.println( "data.a = " + data.a ); } }
こんな感じで使ってみたのさと。
実行結果は、
data.a = 20
のつもりでコード書いてたわけですな。
でもね、でもね
そうです、違うんです
20にはならないんですよね。
10になります。
これ、知ってないと、こんな間違えする人多いんちゃうかな?
おまけ part1
はやい話が、ベースクラスの機能が、派生先のクラス変数の初期化よりも高い優先順位を持ってるってことですねん。SampleAの初期化より優先されるわけです。
尚、先ほどのソースのaの値の変化ですが、
1)BaseClassのinit呼び出しにより SampleAの a=20が実行
2)BaseClassのコンストラクタ実行終了時に、SampleAの変数初期化が入り、 a=10
となる感じでしょうか。
おまけ part2
兄弟(?)的な感じのC#でやると、20なるのでお気を付けてん(笑)
namespace ConsoleApplication1 { abstract class BaseClass { public BaseClass() { init(); } public abstract void init(); } class SampleA:BaseClass { public int a = 10; public override void init() { a = 20; } } class Program { static void Main(string[] args) { SampleA data = new SampleA(); Console.WriteLine("data.a = " + data.a ); } } }
おまけ3
phpでやると、10ですねー。
このあたりのことは、結構、言語仕様によるものなんでしょうね。
abstract class BaseClass { function __construct() { $this->init(); } abstract public function init(); } class SampleA extends BaseClass { public $a=10; public function init() { $a=20; } } $data = new SampleA(); echo $data->a;
「初期化処理」はプログラムの核
下準備(仕込み作業)って、何をするにも重要なことだと思うのですが、プログラムの構造でいえば、それは「初期化」処理にあたると思います。その行為が「不安定」だと、ろくな事にならないです。
上記サンプルのような不安定さを醸し出すコードは、書かない方が良いということでしょうね。
これでご飯を食べる人は特に、注意しないとね。
ではでは♪