oo::class create ClassName { ... }
oo::class create ClassName oo::define ClassName { ... }
ClassName new arg ... => object ClassName create name arg ,,,
% oo::class create Foo ::Foo % set a [Foo new] ::oo::Obj12 % echo $a ::oo::Obj12 % Foo create b ::b
variable name1 name2 ...
constructor {arg ...} { ... }
method method_name {arg ...} { .... }
リスト : 簡単な使用例1 oo::class create Foo { variable a b constructor {x y} { set a $x set b $y } # アクセスメソッド method get_a {} { return $a } method set_a {x} { set a $x } method get_b {} { return $b } method set_b {x} { set b $x } } Foo create obj1 10 20 Foo create obj2 30 40 puts [obj1 get_a] puts [obj1 get_b] puts [obj2 get_a] puts [obj2 get_b] obj1 set_a 100 obj2 set_b 400 puts [obj1 get_a] puts [obj1 get_b] puts [obj2 get_a] puts [obj2 get_b]
C>tclsh oo01.tcl 10 20 30 40 100 20 30 400
obj destroy cls destroy
destructor { ... }
% oo::class create Foo { variable x constructor {a} { set x $a } destructor { puts "destroy Foo $x" } } ::Foo % Foo create a 1 ::a % Foo create b 2 ::b % Foo create c 3 ::c % a destroy destroy Foo 1 % Foo destroy destroy Foo 3 destroy Foo 2
リスト : 簡単な使用例2 oo::class create Point { variable x y constructor {a b} { set x $a set y $b } method get_x {} { return $x } method get_y {} { return $y } method distance {p} { set dx [expr $x - [$p get_x]] set dy [expr $y - [$p get_y]] return [expr sqrt($dx * $dx + $dy * $dy)] } } oo::class create Point3d { variable x y z constructor {a b c} { set x $a set y $b set z $c } method get_x {} { return $x } method get_y {} { return $y } method get_z {} { return $z } method distance {p} { set dx [expr $x - [$p get_x]] set dy [expr $y - [$p get_y]] set dz [expr $z - [$p get_z]] return [expr sqrt($dx * $dx + $dy * $dy + $dz * $dz)] } } Point create p1 0 0 Point create p2 10 10 puts [p1 distance p2] Point3d create p3 0 0 0 Point3d create p4 10 10 10 puts [p3 distance p4]
C>tclsh oo02.tcl 14.142135623730951 17.320508075688775
A. K. デュードニー 著「別冊 日経サイエンス コンピューターレクリエーション3 遊びの発見」 より、 ワーム(ミミズ)のグラフィックです。本では1匹のミミズしか登場しませんが、 このプログラムではミミズを4匹に増やしました。 ミミズは円を連結しているだけの簡単なグラフィックなので、 すぐに飽きると思います。 ミミズの数を増やすとか色や形を変えるなど、プログラムを改造して遊んでみてください。
# # worms.tcl : ワーム # # Copyright (C) 2019 Makoto Hiroi # # 画面の大きさ set board_size 300 # キャンバスの生成 canvas .c0 -width $board_size -height $board_size -bg darkgray pack .c0 # ワームの体を作る proc make_body {color} { global board_size set body {} set x [expr $board_size / 2] for {set i 0} {$i < 25} {incr i} { set id [.c0 create oval $x $x [expr $x + 10] [expr $x + 10] -outline $color] lappend body $id } return $body } # ワーム oo::class create Worm { variable body x y dir tail constructor {color} { global board_size set body [make_body $color] set x [expr $board_size / 2] set y [expr $board_size / 2] set dir 0 set tail 0 } method move_worm {} { global board_size set tail [expr ($tail + 1) % 25] if {[expr rand()] > 0.5} { set dir [expr $dir + 0.18] } else { set dir [expr $dir - 0.18] } set x [expr $x + sin($dir) * 4] if {$x < 0} { set x [expr $x + $board_size] } elseif {$x >= $board_size} { set x [expr $x - $board_size] } set y [expr $y + cos($dir) * 4] if {$y < 0.0} { set y [expr $y + $board_size] } elseif {$y >= $board_size} { set y [expr $y - $board_size] } .c0 coords [lindex $body $tail] $x $y [expr $x + 10] [expr $y + 10] } } # ミミズの生成 Worm create worm1 red Worm create worm2 blue Worm create worm3 yellow Worm create worm4 green # 表示 proc show_worm {} { worm1 move_worm worm2 move_worm worm3 move_worm worm4 move_worm after 40 show_worm } # 実行 show_worm
リスト : 単一継承 oo::class create Foo { variable a b constructor {x y} { set a $x set b $y } # アクセスメソッド method get_a {} { return $a } method set_a {x} { set a $x } method get_b {} { return $b } method set_b {x} { set b $x } } oo::class create Bar { superclass Foo variable c constructor {x y z} { next $x $y set c $z } # アクセスメソッド method get_c {} { return $c } method set_c {x} { set c $x } } Foo create a 10 20 puts [a get_a] puts [a get_b] Bar create b 1 2 3 puts [b get_a] puts [b get_b] puts [b get_c]
10 20 1 2 3
next arg ...
% oo::class create Bar1 { superclass Foo variable a b method get_c {} { return [expr $a + $b] } } ::Bar1 % Bar1 create c 100 200 ::c % c get_c 300
リスト : 左優先則 oo::class create A { method baz {} { next puts "A::baz" } } oo::class create B { method baz {} { puts "B::baz" } } oo::class create C { superclass A B method baz {} { next puts "C::baz" } } C create c puts [info object call c baz] c baz
{method baz ::C method} {method baz ::A method} {method baz ::B method} B::baz A::baz C::baz
A B C │ │ │ │ │ │ D E F \ │ / \│/ G G→D→A→E→B→F→C 図 : 深さ優先則
リスト : 深さ優先則 oo::class create A { method foo {} { next puts "A::foo" } } oo::class create B { method foo {} { puts "B::foo" } } oo::class create C { superclass A method foo {} { next puts "C::foo" } } oo::class create D { superclass B method foo {} { next puts "D::foo" } } oo::class create E { superclass C D method foo {} { next puts "E::foo" } } E create e puts [info object call e foo] e foo
{method foo ::E method} {method foo ::C method} {method foo ::A method} {method foo ::D method} {method foo ::B method} B::foo D::foo A::foo C::foo E::foo
A / \ / \ B C D→B→C→A \ / \ / D 図 : 合流則
リスト : 合流則 oo::class create A { method foo {} { puts "A::foo" } } oo::class create B { superclass A method foo {} { next puts "B::foo" } } oo::class create C { superclass A method foo {} { next puts "C::foo" } } oo::class create D { superclass B C method foo {} { next puts "D::foo" } } D create d puts [info object call d foo] d foo
{method foo ::D method} {method foo ::B method} {method foo ::C method} {method foo ::A method} A::foo C::foo B::foo D::foo
A / B Mixin A / \ Mixin B \ / \ / C D 図 : Mix-in
リスト : Mix-in の簡単な例題 oo::class create Foo { variable x constructor {a} { set x $a } method foo {} { puts "Foo::foo $x" } } oo::class create Bar { method bar_1 {} { puts "bar_1 !" } method bar_2 {} { puts "bar_2 !!" } } oo::class create Baz { superclass Foo mixin Bar method foo {} { next puts "Baz::foo" } } Baz create b 100 b foo b bar_1 b bar_2
Foo::foo 100 Baz::foo bar_1 ! bar_2 !!
info object isa typeof obj cls
% oo::class create Foo ::Foo % oo::class create Bar { superclass Foo } ::Bar % oo::class create Baz { superclass Bar } ::Baz % Foo create a ::a % Bar create b ::b % Baz create c ::c % info object isa typeof a Foo 1 % info object isa typeof a Bar 0 % info object isa typeof b Foo 1 % info object isa typeof b Bar 1 % info object isa typeof b Baz 0 % info object isa typeof c Foo 1 % info object isa typeof c Bar 1 % info object isa typeof c Baz 1
┌──────────┐ │ Foo │ │ ┌──────┐ │ │ │ Bar │ │ │ │ ┌──┐ │ │ │ │ │Baz │ │ │ │ │ │ │ │ │ │ │ └──┘ │ │ │ │ │ │ │ └──────┘ │ │ │ └──────────┘ 図 : クラスとサブクラスの関係
oo::objdefine obj { ... }
% oo::class create Foo ::Foo % Foo create a ::a % Foo create b ::b % oo::objdefine a { method bar {} { puts "bar!!" } } % a bar bar!! % b bar unknown method "bar": must be destroy
% oo::class create Foo ::Foo % oo::objdefine Foo { variable x method get_x {} { return $x } method set_x {a} { set x $a } } % Foo set_x 10 10 % Foo get_x 10 % Foo create a ::a % a get_x unknown method "get_x": must be destroy
% oo::define Foo { method get_x {} { return [[self class] get_x] } method set_x {a} { [self class] set_x $a } } % Foo set_x 1 1 % Foo get_x 1 % Foo create a ::a % a get_x 1 % a set_x 10 10 % Foo create b ::b % b get_x 10 % b set_x 100 100 % a get_x 100 % Foo get_x 100
unexport method_name ...
export method_name ...
% oo::class create Foo { method foo {} { puts "foo!!" } method bar {} { my foo puts "bar!!" } } ::Foo % Foo create a ::a % a foo foo!! % a bar foo!! bar!! % oo::define Foo { unexport foo } % a foo unknown method "foo": must be bar or destroy % a bar foo!! bar!! % oo::define Foo { export foo } % a foo foo!!