オブジェクトのメソッドとか
すごい基本的な内容だけど、こういうのさえマニュアルには無いので困る。オブジェクト関連はOcamlとF#で違うみたいなので、Ocamlもあまり参考にならない。
C#をやってたりするとこういうところで勘が働くのかなあ。
というわけでオブジェクトのコード。
// F#のバージョン: 1.9.2.9 ////////////// オブジェクト type TestBase = class new () = {} // abstract でオーバーライド可能なメソッドを宣言 abstract Test0 : unit -> string abstract Test3 : unit -> string // abstract は default か override でオーバーライドする。 // 両者は異なるバイナリを生成するが、処理的には変わりは無いようだ。 default x.Test0() = "TestBase Test0 abstract" member x.Test1() = "TestBase Test1" member x.Test2() = x.Test0() default x.Test3() = x.Test2() member x.Test4() = x.Test3() override x.Finalize() = printf "Finalize() of %s called!!!\n" (x.ToString()) end let scope_test = fun () -> let temp_object = new TestBase() in printf "temp_object is created\n"; // ここでGCを呼んでもFinalize()は呼ばれない。 System.GC.Collect(); // ここにprintfを入れないと、上のGCが間に合って回収されちゃうことも printf "Finalize() has not been called yet.\n";; do scope_test() // Finalize() はスコープ外にでた瞬間には呼ばれない。 do printf "Finalize() has not been called yet.\n" // ここでGCさせるとFinalize()が呼ばれる。 do System.GC.Collect() let testbase = new TestBase() // default で宣言した関数を呼ぶ。 // 引数部分はこの場合カッコで囲まないとコンパイルエラー。 do printf "abstract TestBase.Test0() = '%s'\n" (testbase.Test0()) // abstract と member の混在 do printf "member TestBase.Test4() = '%s'\n" (testbase.Test4()) // abstract なオブジェクトはコンストラクト時にオーバーライド可能 // member は不可。また、フィールドも不可(mutable でも不可)。 // フィールドの初期化はclassのコンストラクタ内で行うべし。 let testbase2 = {new TestBase() with Test0() = "TestBase Test0 overrided when construction"} do printf "member TestBase.Test4() = '%s'\n" (testbase2.Test4()) ////////////// 継承やらオーバーライドやら type TestSub = class inherit TestBase as base new() = { } // メソッドをオーバーライド。 override x.Test0() = "TestSub Test0" // Test2 を上書き。 member x.Test2() = x.Test1() end let testsub = new TestSub() // オーバーライドしたメソッドを呼ぶ do printf "abstract TestSub.Test0() = '%s'\n" (testsub.Test0()) // abstract の関数をTestBaseにキャストして呼んでも同じ do printf "abstract (TestSub :> TestBase).Test0() = '%s'\n" ( (testsub :> TestBase).Test0()) // 通常(abstract でない)の上書きしたメソッドを呼ぶ do printf "member TestSub.Test2 = '%s'\n" (testsub.Test2()) // 通常の上書きしたメソッドをTestBaseにキャストして呼ぶと、 // TestBaseのメソッドが呼ばれる。(その結果、上書きしたTest0が呼ばれる) do printf "member (TestSub :> TestBase).Test2 = '%s'\n" ( (testsub :> TestBase).Test2()) // Test3スロットにはTestBase.Test2が入っているので、 // TestBaseにキャストした場合のTest2と同じ結果になる do printf "abstract TestSub.Test3 = '%s'\n" (testsub.Test3()) ////////////// さらに継承 type TestSubSub = class inherit TestSub as base new() = { } override x.Test0() = "TestSubSub Test0" override x.Test3() = x.Test2() end let testsubsub = new TestSubSub() // Test3のスロットにTestSubSub1のものが入っているので、キャストしても同じ do printf "member TestSubSub.Test4 = '%s'\n" (testsubsub.Test4()) do printf "member (TestSubSub :> TestSub).Test4 = '%s'\n" ( (testsubsub :> TestSub).Test4()) do printf "member (TestSubSub :> TestBase).Test4 = '%s'\n" ( (testsubsub :> TestSub).Test4())