TclOOのcreateとnewの違い

元ネタは「[tcl - TclOOを使用したオブジェクト作成での新規作成と新規作成](https://ja.coder.work/so/tcl/2186529)」というページです。機械翻訳なんですかね、「新規作成と新規作成」って・・・

TclOOでクラスのインスタンスを生成するコマンドとして「create」と「new」があって、前者がインスタンスの名前を明示的に与えるのに対し、後者は自動命名してくれるという違いがあるのですが、「create」のヘルプの「This creates a new instance of the class cls called name (which is resolved within the calling context's namespace if not fully qualified)」の括弧書きの部分をきちんと説明してくれているのが元ネタの内容です。

そして元ネタの説明で「へー」っと思ったのが「寿命管理」の違い。

クラスのデストラクタが実行される際、「包含」とか「has-a」と呼ばれるインスタンスのデストラクタも呼ばれるのか呼ばれないのかの違いがあるようです。

というわけで、何通りか実験コードを書いて、挙動を比べてみました。(inner1とinner2がhas-a関係のインスタンス)

```tcl:tcloo_sample.tcl
#!/bin/sh
#-*-mode:tcl;tab-width:4;coding:cp932-*-\
    exec tclsh8.6 -encoding cp932 "$0" "$@"

# tcl - TclOOを使用したオブジェクト作成での新規作成と新規作成
# https://ja.coder.work/so/tcl/2186529

oo::class create InsideThing {
    constructor {} {
        puts "Made a [self] that is an InsideThing"
    }
    destructor {
        puts "Deleted a [self] that is an InsideThing"
    }
}
oo::class create Container {
    constructor {} {
        puts "Created a [self] that is a Container"
        InsideThing create inner1
        InsideThing create inner2
    }
    destructor {
        puts "Deleted a [self] that is a Container"
    }
}

# 比較用

oo::class create Container2 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container2"
        set it1 [InsideThing create inner1]
        set it2 [InsideThing create inner2]
    }
    destructor {
        puts "Deleted a [self] that is a Container2"
    }
}

oo::class create Container3 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container3"
        set it1 [InsideThing create inner1]
        set it2 [InsideThing create inner2]
    }
    destructor {
        puts "Deleted a [self] that is a Container3"
        $it1 destroy
        $it2 destroy
    }
}

oo::class create Container4 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container4"
        set it1 [InsideThing create [namespace current]::inner1]
        set it2 [InsideThing create [namespace current]::inner2]
    }
    destructor {
        puts "Deleted a [self] that is a Container4"
    }
}

oo::class create Container5 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container5"
        set it1 [InsideThing create ::inner1]
        set it2 [InsideThing create ::inner2]
    }
    destructor {
        puts "Deleted a [self] that is a Container5"
        $it1 destroy
        $it2 destroy
    }
}

oo::class create Container6 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container6"
        set it1 [InsideThing create ::inner1]
        set it2 [InsideThing create ::inner2]
    }
    destructor {
        puts "Deleted a [self] that is a Container6"
    }
}

oo::class create Container7 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container7"
        set it1 [InsideThing new]
        set it2 [InsideThing new]
    }
    destructor {
        puts "Deleted a [self] that is a Container7"
    }
}

oo::class create Container8 {
    variable it1
    variable it2
    constructor {} {
        puts "Created a [self] that is a Container8"
        set it1 [InsideThing new]
        set it2 [InsideThing new]
    }
    destructor {
        puts "Deleted a [self] that is a Container8"
        $it1 destroy
        $it2 destroy
    }
}

puts "Test Container (createで生成したInsideThingのインスタンスが暗黙的にdestroyされる例 元ネタ)\n"
set c [Container new]
$c destroy

puts "\nTest Container2 (createで生成したInsideThingのインスタンスが暗黙的にdestroyされる例 その2)\n"
set c2 [Container2 new]
$c2 destroy

puts "\nTest Container3 (createで生成したのでInsideThingのインスタンスが暗黙的にdestroyされるのに明示的にdestroyしてしまった例)\n"
set c3 [Container3 new]
$c3 destroy

puts "\nTest Container3 (destroyされたInsideThingのインスタンスをdestroyしてみた例)\n"
if {[catch {${c3}::inner1 destory} message]} {
    puts $message
}
if {[catch {${c3}::inner2 destory} message]} {
    puts $message
}

puts "\nTest Container4 (createで生成したInsideThingのインスタンスが暗黙的にdestroyされる例 その3)\n"
set c4 [Container4 new]
$c4 destroy

puts "\nTest Container5 (createで生成したInsideThingのインスタンスを明示的にdestroyする例)\n"
set c5 [Container5 new]
$c5 destroy

puts "\nTest Container6 (createで生成したのにInsideThingのインスタンスが暗黙的にdestroyされない例)\n"
set c6 [Container6 new]
$c6 destroy

puts "\nTest Container7 (newで生成したのでInsideThingのインスタンスが暗黙的にdestroyされない例)\n"
set c7 [Container7 new]
$c7 destroy

puts "\nTest Container8 (newで生成したのでInsideThingのインスタンスを明示的にdestroyする例)\n"
set c8 [Container8 new]
$c8 destroy
```
実行結果は以下の通り。

要は生成された「has-a」インスタンスのfully-qualified nameがどうなってるか、というところに帰結するわけで、createでも別の名前空間に命名すれば暗黙的にdestroyされないので「newとcreateの違い」とするのはちょっとどうかなと感じました。

```
Test Container (createで生成したInsideThingのインスタンスが暗黙的にdestroyされる例 元ネタ)

Created a ::oo::Obj20 that is a Container
Made a ::oo::Obj20::inner1 that is an InsideThing
Made a ::oo::Obj20::inner2 that is an InsideThing
Deleted a ::oo::Obj20 that is a Container
Deleted a ::oo::Obj20::inner1 that is an InsideThing
Deleted a ::oo::Obj20::inner2 that is an InsideThing

Test Container2 (createで生成したInsideThingのインスタンスが暗黙的にdestroyされる例 その2)

Created a ::oo::Obj23 that is a Container2
Made a ::oo::Obj23::inner1 that is an InsideThing
Made a ::oo::Obj23::inner2 that is an InsideThing
Deleted a ::oo::Obj23 that is a Container2
Deleted a ::oo::Obj23::inner1 that is an InsideThing
Deleted a ::oo::Obj23::inner2 that is an InsideThing

Test Container3 (createで生成したのでInsideThingのインスタンスが暗黙的にdestroyされるのに明示的にdestroyしてしまった例)

Created a ::oo::Obj26 that is a Container3
Made a ::oo::Obj26::inner1 that is an InsideThing
Made a ::oo::Obj26::inner2 that is an InsideThing
Deleted a ::oo::Obj26 that is a Container3
Deleted a ::oo::Obj26::inner1 that is an InsideThing
Deleted a ::oo::Obj26::inner2 that is an InsideThing

Test Container3 (destroyされたInsideThingのインスタンスをdestroyしてみた例)

invalid command name "::oo::Obj26::inner1"
invalid command name "::oo::Obj26::inner2"

Test Container4 (createで生成したInsideThingのインスタンスが暗黙的にdestroyされる例 その3)

Created a ::oo::Obj29 that is a Container4
Made a ::oo::Obj29::inner1 that is an InsideThing
Made a ::oo::Obj29::inner2 that is an InsideThing
Deleted a ::oo::Obj29 that is a Container4
Deleted a ::oo::Obj29::inner1 that is an InsideThing
Deleted a ::oo::Obj29::inner2 that is an InsideThing

Test Container5 (createで生成したInsideThingのインスタンスを明示的にdestroyする例)

Created a ::oo::Obj32 that is a Container5
Made a ::inner1 that is an InsideThing
Made a ::inner2 that is an InsideThing
Deleted a ::oo::Obj32 that is a Container5
Deleted a ::inner1 that is an InsideThing
Deleted a ::inner2 that is an InsideThing

Test Container6 (createで生成したのにInsideThingのインスタンスが暗黙的にdestroyされない例)

Created a ::oo::Obj35 that is a Container6
Made a ::inner1 that is an InsideThing
Made a ::inner2 that is an InsideThing
Deleted a ::oo::Obj35 that is a Container6

Test Container7 (newで生成したのでInsideThingのインスタンスが暗黙的にdestroyされない例)

Created a ::oo::Obj38 that is a Container7
Made a ::oo::Obj39 that is an InsideThing
Made a ::oo::Obj40 that is an InsideThing
Deleted a ::oo::Obj38 that is a Container7

Test Container8 (newで生成したのでInsideThingのインスタンスを明示的にdestroyする例)

Created a ::oo::Obj41 that is a Container8
Made a ::oo::Obj42 that is an InsideThing
Made a ::oo::Obj43 that is an InsideThing
Deleted a ::oo::Obj41 that is a Container8
Deleted a ::oo::Obj42 that is an InsideThing
Deleted a ::oo::Obj43 that is an InsideThing
```