1 2[//000000001]: # (snitfaq \- Snit's Not Incr Tcl, OO system) 3[//000000002]: # (Generated from file 'snitfaq\.man' by tcllib/doctools with format 'markdown') 4[//000000003]: # (Copyright © 2003\-2006, by William H\. Duquette) 5[//000000004]: # (snitfaq\(n\) 2\.2 tcllib "Snit's Not Incr Tcl, OO system") 6 7<hr> [ <a href="../../../../toc.md">Main Table Of Contents</a> | <a 8href="../../../toc.md">Table Of Contents</a> | <a 9href="../../../../index.md">Keyword Index</a> | <a 10href="../../../../toc0.md">Categories</a> | <a 11href="../../../../toc1.md">Modules</a> | <a 12href="../../../../toc2.md">Applications</a> ] <hr> 13 14# NAME 15 16snitfaq \- Snit Frequently Asked Questions 17 18# <a name='toc'></a>Table Of Contents 19 20 - [Table Of Contents](#toc) 21 22 - [Description](#section1) 23 24 - [OVERVIEW](#section2) 25 26 - [What is this document?](#subsection1) 27 28 - [What is Snit?](#subsection2) 29 30 - [What version of Tcl does Snit require?](#subsection3) 31 32 - [Where can I download Snit?](#subsection4) 33 34 - [What are Snit's goals?](#subsection5) 35 36 - [How is Snit different from other OO frameworks?](#subsection6) 37 38 - [What can I do with Snit?](#subsection7) 39 40 - [SNIT VERSIONS](#section3) 41 42 - [Which version of Snit should I use?](#subsection8) 43 44 - [How do I select the version of Snit I want to use?](#subsection9) 45 46 - [How are Snit 1\.3 and Snit 2\.2 incompatible?](#subsection10) 47 48 - [Are there other differences between Snit 1\.x and Snit 49 2\.2?](#subsection11) 50 51 - [OBJECTS](#section4) 52 53 - [What is an object?](#subsection12) 54 55 - [What is an abstract data type?](#subsection13) 56 57 - [What kinds of abstract data types does Snit 58 provide?](#subsection14) 59 60 - [What is a snit::type?](#subsection15) 61 62 - [What is a snit::widget?, the short story](#subsection16) 63 64 - [What is a snit::widgetadaptor?, the short story](#subsection17) 65 66 - [How do I create an instance of a snit::type?](#subsection18) 67 68 - [How do I refer to an object indirectly?](#subsection19) 69 70 - [How can I generate the object name automatically?](#subsection20) 71 72 - [Can types be renamed?](#subsection21) 73 74 - [Can objects be renamed?](#subsection22) 75 76 - [How do I destroy a Snit object?](#subsection23) 77 78 - [INSTANCE METHODS](#section5) 79 80 - [What is an instance method?](#subsection24) 81 82 - [How do I define an instance method?](#subsection25) 83 84 - [How does a client call an instance method?](#subsection26) 85 86 - [How does an instance method call another instance 87 method?](#subsection27) 88 89 - [Are there any limitations on instance method 90 names?](#subsection28) 91 92 - [What is a hierarchical method?](#subsection29) 93 94 - [How do I define a hierarchical method?](#subsection30) 95 96 - [How do I call hierarchical methods?](#subsection31) 97 98 - [How do I make an instance method private?](#subsection32) 99 100 - [Are there any limitations on instance method 101 arguments?](#subsection33) 102 103 - [What implicit arguments are passed to each instance 104 method?](#subsection34) 105 106 - [What is $type?](#subsection35) 107 108 - [What is $self?](#subsection36) 109 110 - [What is $selfns?](#subsection37) 111 112 - [What is $win?](#subsection38) 113 114 - [How do I pass an instance method as a callback?](#subsection39) 115 116 - [How do I delegate instance methods to a component?](#subsection40) 117 118 - [INSTANCE VARIABLES](#section6) 119 120 - [What is an instance variable?](#subsection41) 121 122 - [How is a scalar instance variable defined?](#subsection42) 123 124 - [How is an array instance variable defined?](#subsection43) 125 126 - [What happens if I don't initialize an instance 127 variable?](#subsection44) 128 129 - [Are there any limitations on instance variable 130 names?](#subsection45) 131 132 - [Do I need to declare my instance variables in my 133 methods?](#subsection46) 134 135 - [How do I pass an instance variable's name to another 136 object?](#subsection47) 137 138 - [How do I make an instance variable public?](#subsection48) 139 140 - [OPTIONS](#section7) 141 142 - [What is an option?](#subsection49) 143 144 - [How do I define an option?](#subsection50) 145 146 - [How can a client set options at object creation?](#subsection51) 147 148 - [How can a client retrieve an option's value?](#subsection52) 149 150 - [How can a client set options after object 151 creation?](#subsection53) 152 153 - [How should an instance method access an option 154 value?](#subsection54) 155 156 - [How can I make an option read\-only?](#subsection55) 157 158 - [How can I catch accesses to an option's value?](#subsection56) 159 160 - [What is a \-cgetmethod?](#subsection57) 161 162 - [How can I catch changes to an option's value?](#subsection58) 163 164 - [What is a \-configuremethod?](#subsection59) 165 166 - [How can I validate an option's value?](#subsection60) 167 168 - [What is a \-validatemethod?](#subsection61) 169 170 - [TYPE VARIABLES](#section8) 171 172 - [What is a type variable?](#subsection62) 173 174 - [How is a scalar type variable defined?](#subsection63) 175 176 - [How is an array\-valued type variable defined?](#subsection64) 177 178 - [What happens if I don't initialize a type 179 variable?](#subsection65) 180 181 - [Are there any limitations on type variable names?](#subsection66) 182 183 - [Do I need to declare my type variables in my 184 methods?](#subsection67) 185 186 - [How do I pass a type variable's name to another 187 object?](#subsection68) 188 189 - [How do I make a type variable public?](#subsection69) 190 191 - [TYPE METHODS](#section9) 192 193 - [What is a type method?](#subsection70) 194 195 - [How do I define a type method?](#subsection71) 196 197 - [How does a client call a type method?](#subsection72) 198 199 - [Are there any limitations on type method names?](#subsection73) 200 201 - [How do I make a type method private?](#subsection74) 202 203 - [Are there any limitations on type method 204 arguments?](#subsection75) 205 206 - [How does an instance or type method call a type 207 method?](#subsection76) 208 209 - [How do I pass a type method as a callback?](#subsection77) 210 211 - [Can type methods be hierarchical?](#subsection78) 212 213 - [PROCS](#section10) 214 215 - [What is a proc?](#subsection79) 216 217 - [How do I define a proc?](#subsection80) 218 219 - [Are there any limitations on proc names?](#subsection81) 220 221 - [How does a method call a proc?](#subsection82) 222 223 - [How can I pass a proc to another object as a 224 callback?](#subsection83) 225 226 - [TYPE CONSTRUCTORS](#section11) 227 228 - [What is a type constructor?](#subsection84) 229 230 - [How do I define a type constructor?](#subsection85) 231 232 - [CONSTRUCTORS](#section12) 233 234 - [What is a constructor?](#subsection86) 235 236 - [How do I define a constructor?](#subsection87) 237 238 - [What does the default constructor do?](#subsection88) 239 240 - [Can I choose a different set of arguments for the 241 constructor?](#subsection89) 242 243 - [Are there any limitations on constructor 244 arguments?](#subsection90) 245 246 - [Is there anything special about writing the 247 constructor?](#subsection91) 248 249 - [DESTRUCTORS](#section13) 250 251 - [What is a destructor?](#subsection92) 252 253 - [How do I define a destructor?](#subsection93) 254 255 - [Are there any limitations on destructor arguments?](#subsection94) 256 257 - [What implicit arguments are passed to the 258 destructor?](#subsection95) 259 260 - [Must components be destroyed explicitly?](#subsection96) 261 262 - [Is there any special about writing a destructor?](#subsection97) 263 264 - [COMPONENTS](#section14) 265 266 - [What is a component?](#subsection98) 267 268 - [How do I declare a component?](#subsection99) 269 270 - [How is a component named?](#subsection100) 271 272 - [Are there any limitations on component names?](#subsection101) 273 274 - [What is an owned component?](#subsection102) 275 276 - [What does the install command do?](#subsection103) 277 278 - [Must owned components be created in the 279 constructor?](#subsection104) 280 281 - [Are there any limitations on component object 282 names?](#subsection105) 283 284 - [Must I destroy the components I own?](#subsection106) 285 286 - [Can I expose a component's object command as part of my 287 interface?](#subsection107) 288 289 - [How do I expose a component's object command?](#subsection108) 290 291 - [TYPE COMPONENTS](#section15) 292 293 - [What is a type component?](#subsection109) 294 295 - [How do I declare a type component?](#subsection110) 296 297 - [How do I install a type component?](#subsection111) 298 299 - [Are there any limitations on type component 300 names?](#subsection112) 301 302 - [DELEGATION](#section16) 303 304 - [What is delegation?](#subsection113) 305 306 - [How can I delegate a method to a component 307 object?](#subsection114) 308 309 - [Can I delegate to a method with a different name?](#subsection115) 310 311 - [Can I delegate to a method with additional 312 arguments?](#subsection116) 313 314 - [Can I delegate a method to something other than an 315 object?](#subsection117) 316 317 - [How can I delegate a method to a type component 318 object?](#subsection118) 319 320 - [How can I delegate a type method to a type component 321 object?](#subsection119) 322 323 - [How can I delegate an option to a component 324 object?](#subsection120) 325 326 - [Can I delegate to an option with a different 327 name?](#subsection121) 328 329 - [How can I delegate any unrecognized method or option to a component 330 object?](#subsection122) 331 332 - [How can I delegate all but certain methods or options to a 333 component?](#subsection123) 334 335 - [Can a hierarchical method be delegated?](#subsection124) 336 337 - [WIDGETS](#section17) 338 339 - [What is a snit::widget?](#subsection125) 340 341 - [How do I define a snit::widget?](#subsection126) 342 343 - [How do snit::widgets differ from snit::types?](#subsection127) 344 345 - [What is a hull component?](#subsection128) 346 347 - [How can I set the hull type for a snit::widget?](#subsection129) 348 349 - [How should I name widgets which are components of a 350 snit::widget?](#subsection130) 351 352 - [WIDGET ADAPTORS](#section18) 353 354 - [What is a snit::widgetadaptor?](#subsection131) 355 356 - [How do I define a snit::widgetadaptor?](#subsection132) 357 358 - [Can I adapt a widget created elsewhere in the 359 program?](#subsection133) 360 361 - [Can I adapt another megawidget?](#subsection134) 362 363 - [THE TK OPTION DATABASE](#section19) 364 365 - [What is the Tk option database?](#subsection135) 366 367 - [Do snit::types use the Tk option database?](#subsection136) 368 369 - [What is my snit::widget's widget class?](#subsection137) 370 371 - [What is my snit::widgetadaptor's widget class?](#subsection138) 372 373 - [What are option resource and class names?](#subsection139) 374 375 - [What are the resource and class names for my megawidget's 376 options?](#subsection140) 377 378 - [How does Snit initialize my megawidget's locally\-defined 379 options?](#subsection141) 380 381 - [How does Snit initialize delegated options?](#subsection142) 382 383 - [How does Snit initialize options delegated to the 384 hull?](#subsection143) 385 386 - [How does Snit initialize options delegated to other 387 components?](#subsection144) 388 389 - [What happens if I install a non\-widget as a component of 390 widget?](#subsection145) 391 392 - [ENSEMBLE COMMANDS](#section20) 393 394 - [What is an ensemble command?](#subsection146) 395 396 - [How can I create an ensemble command using Snit?](#subsection147) 397 398 - [How can I create an ensemble command using an instance of a 399 snit::type?](#subsection148) 400 401 - [How can I create an ensemble command using a 402 snit::type?](#subsection149) 403 404 - [PRAGMAS](#section21) 405 406 - [What is a pragma?](#subsection150) 407 408 - [How do I set a pragma?](#subsection151) 409 410 - [How can I get rid of the "info" type method?](#subsection152) 411 412 - [How can I get rid of the "destroy" type method?](#subsection153) 413 414 - [How can I get rid of the "create" type method?](#subsection154) 415 416 - [How can I get rid of type methods altogether?](#subsection155) 417 418 - [Why can't I create an object that replaces an old object with the same 419 name?](#subsection156) 420 421 - [How can I make my simple type run faster?](#subsection157) 422 423 - [MACROS](#section22) 424 425 - [What is a macro?](#subsection158) 426 427 - [What are macros good for?](#subsection159) 428 429 - [How do I do conditional compilation?](#subsection160) 430 431 - [How do I define new type definition syntax?](#subsection161) 432 433 - [Are there are restrictions on macro names?](#subsection162) 434 435 - [Bugs, Ideas, Feedback](#section23) 436 437 - [Keywords](#keywords) 438 439 - [Category](#category) 440 441 - [Copyright](#copyright) 442 443# <a name='description'></a>DESCRIPTION 444 445# <a name='section2'></a>OVERVIEW 446 447## <a name='subsection1'></a>What is this document? 448 449This is an atypical FAQ list, in that few of the questions are frequently asked\. 450Rather, these are the questions I think a newcomer to Snit should be asking\. 451This file is not a complete reference to Snit, however; that information is in 452the __[snit](snit\.md)__ man page\. 453 454## <a name='subsection2'></a>What is Snit? 455 456Snit is a framework for defining abstract data types and megawidgets in pure 457Tcl\. The name "Snit" stands for "Snit's Not Incr Tcl", signifying that Snit 458takes a different approach to defining objects than does Incr Tcl, the best 459known object framework for Tcl\. Had I realized that Snit would become at all 460popular, I'd probably have chosen something else\. 461 462The primary purpose of Snit is to be *object glue*\-\-to help you compose 463diverse objects from diverse sources into types and megawidgets with clean, 464convenient interfaces so that you can more easily build your application\. 465 466Snit isn't about theoretical purity or minimalist design; it's about being able 467to do powerful things easily and consistently without having to think about 468them\-\-so that you can concentrate on building your application\. 469 470Snit isn't about implementing thousands of nearly identical carefully\-specified 471lightweight thingamajigs\-\-not as individual Snit objects\. Traditional Tcl 472methods will be much faster, and not much more complicated\. But Snit *is* 473about implementing a clean interface to manage a collection of thousands of 474nearly identical carefully\-specified lightweight thingamajigs \(e\.g\., think of 475the text widget and text tags, or the canvas widget and canvas objects\)\. Snit 476lets you hide the details of just how those thingamajigs are stored\-\-so that you 477can ignore it, and concentrate on building your application\. 478 479Snit isn't a way of life, a silver bullet, or the Fountain of Youth\. It's just a 480way of managing complexity\-\-and of managing some of the complexity of managing 481complexity\-\-so that you can concentrate on building your application\. 482 483## <a name='subsection3'></a>What version of Tcl does Snit require? 484 485Snit 1\.3 requires Tcl 8\.3 or later; Snit 2\.2 requires Tcl 8\.5 or later\. See 486[SNIT VERSIONS](#section3) for the differences between Snit 1\.3 and Snit 4872\.2\. 488 489## <a name='subsection4'></a>Where can I download Snit? 490 491Snit is part of Tcllib, the standard Tcl library, so you might already have it\. 492It's also available at the Snit Home Page, 493[http://www\.wjduquette\.com/snit](http://www\.wjduquette\.com/snit)\. 494 495## <a name='subsection5'></a>What are Snit's goals? 496 497 - A Snit object should be at least as efficient as a hand\-coded Tcl object 498 \(see 499 [http://www\.wjduquette\.com/tcl/objects\.html](http://www\.wjduquette\.com/tcl/objects\.html)\)\. 500 501 - The fact that Snit was used in an object's implementation should be 502 transparent \(and irrelevant\) to clients of that object\. 503 504 - Snit should be able to encapsulate objects from other sources, particularly 505 Tk widgets\. 506 507 - Snit megawidgets should be \(to the extent possible\) indistinguishable in 508 interface from Tk widgets\. 509 510 - Snit should be Tclish\-\-that is, rather than trying to emulate C\+\+, 511 Smalltalk, or anything else, it should try to emulate Tcl itself\. 512 513 - It should have a simple, easy\-to\-use, easy\-to\-remember syntax\. 514 515## <a name='subsection6'></a>How is Snit different from other OO frameworks? 516 517Snit is unique among Tcl object systems in that it is based not on inheritance 518but on delegation\. Object systems based on inheritance only allow you to inherit 519from classes defined using the same system, and that's a shame\. In Tcl, an 520object is anything that acts like an object; it shouldn't matter how the object 521was implemented\. I designed Snit to help me build applications out of the 522materials at hand; thus, Snit is designed to be able to incorporate and build on 523any object, whether it's a hand\-coded object, a Tk widget, an Incr Tcl object, a 524BWidget or almost anything else\. 525 526Note that you can achieve the effect of inheritance using 527[COMPONENTS](#section14) and [DELEGATION](#section16)\-\-and you can 528inherit from anything that looks like a Tcl object\. 529 530## <a name='subsection7'></a>What can I do with Snit? 531 532Using Snit, a programmer can: 533 534 - Create abstract data types and Tk megawidgets\. 535 536 - Define instance variables, type variables, and Tk\-style options\. 537 538 - Define constructors, destructors, instance methods, type methods, procs\. 539 540 - Assemble a type out of component types\. Instance methods and options can be 541 delegated to the component types automatically\. 542 543# <a name='section3'></a>SNIT VERSIONS 544 545## <a name='subsection8'></a>Which version of Snit should I use? 546 547The current Snit distribution includes two versions, Snit 1\.3 and Snit 2\.2\. The 548reason that both are included is that Snit 2\.2 takes advantage of a number of 549new features of Tcl 8\.5 to improve run\-time efficiency; as a side\-effect, the 550ugliness of Snit's error messages and stack traces has been reduced 551considerably\. The cost of using Snit 2\.2, of course, is that you must target Tcl 5528\.5\. 553 554Snit 1\.3, on the other hand, lacks Snit 2\.2's optimizations, but requires only 555Tcl 8\.3 and later\. 556 557In short, if you're targetting Tcl 8\.3 or 8\.4 you should use Snit 1\.3\. If you 558can afford to target Tcl 8\.5, you should definitely use Snit 2\.2\. If you will be 559targetting both, you can use Snit 1\.3 exclusively, or \(if your code is 560unaffected by the minor incompatibilities between the two versions\) you can use 561Snit 1\.3 for Tcl 8\.4 and Snit 2\.2 for Tcl 8\.5\. 562 563## <a name='subsection9'></a>How do I select the version of Snit I want to use? 564 565To always use Snit 1\.3 \(or a later version of Snit 1\.x\), invoke Snit as follows: 566 567 package require snit 1.3 568 569To always use Snit 2\.2 \(or a later version of Snit 2\.x\), say this instead: 570 571 package require snit 2.2 572 573Note that if you request Snit 2\.2 explicitly, your application will halt with 574Tcl 8\.4, since Snit 2\.2 is unavailable for Tcl 8\.4\. 575 576If you wish your application to always use the latest available version of Snit, 577don't specify a version number: 578 579 package require snit 580 581Tcl will find and load the latest version that's available relative to the 582version of Tcl being used\. In this case, be careful to avoid using any 583incompatible features\. 584 585## <a name='subsection10'></a>How are Snit 1\.3 and Snit 2\.2 incompatible? 586 587To the extent possible, Snit 2\.2 is intended to be a drop\-in replacement for 588Snit 1\.3\. Unfortunately, some incompatibilities were inevitable because Snit 2\.2 589uses Tcl 8\.5's new __namespace ensemble__ mechanism to implement subcommand 590dispatch\. This approach is much faster than the mechanism used in Snit 1\.3, and 591also results in much better error messages; however, it also places new 592constraints on the implementation\. 593 594There are four specific incompatibilities between Snit 1\.3 and Snit 2\.2\. 595 596 - Snit 1\.3 supports implicit naming of objects\. Suppose you define a new 597 __snit::type__ called __dog__\. You can create instances of 598 __dog__ in three ways: 599 600 dog spot ;# Explicit naming 601 set obj1 [dog %AUTO%] ;# Automatic naming 602 set obj2 [dog] ;# Implicit naming 603 604 In Snit 2\.2, type commands are defined using the __namespace ensemble__ 605 mechanism; and __namespace ensemble__ doesn't allow an ensemble command 606 to be called without a subcommand\. In short, using __namespace 607 ensemble__ there's no way to support implicit naming\. 608 609 All is not lost, however\. If the type has no type methods, then the type 610 command is a simple command rather than an ensemble, and __namespace 611 ensemble__ is not used\. In this case, implicit naming is still possible\. 612 613 In short, you can have implicit naming if you're willing to do without type 614 methods \(including the standard type methods, like __$type info__\)\. To 615 do so, use the __\-hastypemethods__ pragma: 616 617 pragma -hastypemethods 0 618 619 - Hierarchical methods and type methods are implemented differently in Snit 620 2\.2\. 621 622 A hierarchical method is an instance method which has subcommands; these 623 subcommands are themselves methods\. The Tk text widget's __tag__ command 624 and its subcommands are examples of hierarchical methods\. You can implement 625 such subcommands in Snit simply by including multiple words in the method 626 names: 627 628 method {tag configure} {tag args} { ... } 629 630 method {tag cget} {tag option} {...} 631 632 Here we've implicitly defined a __tag__ method which has two 633 subcommands, __configure__ and __cget__\. 634 635 In Snit 1\.3, hierarchical methods could be called in two ways: 636 637 $obj tag cget -myoption ;# The good way 638 $obj {tag cget} -myoption ;# The weird way 639 640 In the second call, we see that a hierarchical method or type method is 641 simply one whose name contains multiple words\. 642 643 In Snit 2\.2 this is no longer the case, and the "weird" way of calling 644 hierarchical methods and type methods no longer works\. 645 646 - The third incompatibility derives from the second\. In Snit 1\.3, hierarchical 647 methods were also simply methods whose name contains multiple words\. As a 648 result, __$obj info methods__ returned the full names of all 649 hierarchical methods\. In the example above, the list returned by __$obj 650 info methods__ would include __tag configure__ and __tag cget__ 651 but not __tag__, since __tag__ is defined only implicitly\. 652 653 In Snit 2\.2, hierarchical methods and type methods are no longer simply ones 654 whose name contains multiple words; in the above example, the list returned 655 by __$obj info methods__ would include __tag__ but not __tag 656 configure__ or __tag cget__\. 657 658 - The fourth incompatibility is due to a new feature\. Snit 2\.2 uses the new 659 __namespace path__ command so that a type's code can call any command 660 defined in the type's parent namespace without qualification or importation\. 661 For example, suppose you have a package called __mypackage__ which 662 defines a number of commands including a type, __::mypackage::mytype__\. 663 Thanks to __namespace path__, the type's code can call any of the other 664 commands defined in __::mypackage::__\. 665 666 This is extremely convenient\. However, it also means that commands defined 667 in the parent namespace, __::mypackage::__ can block the type's access 668 to identically named commands in the global namespace\. This can lead to 669 bugs\. For example, Tcllib includes a type called __::tie::std::file__\. 670 This type's code calls the standard 671 __[file](\.\./\.\./\.\./\.\./index\.md\#file)__ command\. When run with Snit 672 2\.2, the code broke\-\- the type's command, __::tie::std::file__, is 673 itself a command in the type's parent namespace, and so instead of calling 674 the standard __[file](\.\./\.\./\.\./\.\./index\.md\#file)__ command, the type 675 found itself calling itself\. 676 677## <a name='subsection11'></a>Are there other differences between Snit 1\.x and Snit 2\.2? 678 679Yes\. 680 681 - Method dispatch is considerably faster\. 682 683 - Many error messages and stack traces are cleaner\. 684 685 - The __\-simpledispatch__ pragma is obsolete, and ignored if present\. In 686 Snit 1\.x, __\-simpledispatch__ substitutes a faster mechanism for method 687 dispatch, at the cost of losing certain features\. Snit 2\.2 method dispatch 688 is faster still in all cases, so __\-simpledispatch__ is no longer 689 needed\. 690 691 - In Snit 2\.2, a type's code \(methods, type methods, etc\.\) can call commands 692 from the type's parent namespace without qualifying or importing them, i\.e\., 693 type __::parentns::mytype__'s code can call __::parentns::someproc__ 694 as just __someproc__\. 695 696 This is extremely useful when a type is defined as part of a larger package, 697 and shares a parent namespace with the rest of the package; it means that 698 the type can call other commands defined by the package without any extra 699 work\. 700 701 This feature depends on the new Tcl 8\.5 __namespace path__ command, 702 which is why it hasn't been implemented for V1\.x\. V1\.x code can achieve 703 something similar by placing 704 705 namespace import [namespace parent]::* 706 707 in a type constructor\. This is less useful, however, as it picks up only 708 those commands which have already been exported by the parent namespace at 709 the time the type is defined\. 710 711# <a name='section4'></a>OBJECTS 712 713## <a name='subsection12'></a>What is an object? 714 715A full description of object\-oriented programming is beyond the scope of this 716FAQ, obviously\. In simple terms, an object is an instance of an abstract data 717type\-\-a coherent bundle of code and data\. There are many ways to represent 718objects in Tcl/Tk; the best known examples are the Tk widgets\. 719 720A Tk widget is an object; it is represented by a Tcl command\. The object's 721methods are subcommands of the Tcl command\. The object's properties are options 722accessed using the __configure__ and __cget__ methods\. Snit uses the 723same conventions as Tk widgets do\. 724 725## <a name='subsection13'></a>What is an abstract data type? 726 727In computer science terms, an abstract data type is a complex data structure 728along with a set of operations\-\-a stack, a queue, a binary tree, etc\-\-that is to 729say, in modern terms, an object\. In systems that include some form of 730inheritance the word *[class](\.\./\.\./\.\./\.\./index\.md\#class)* is usually used 731instead of *abstract data type*, but as Snit doesn't implement inheritance as 732it's ordinarily understood the older term seems more appropriate\. Sometimes this 733is called *object\-based* programming as opposed to object\-oriented 734programming\. Note that you can easily create the effect of inheritance using 735[COMPONENTS](#section14) and [DELEGATION](#section16)\. 736 737In Snit, as in Tk, a *[type](\.\./\.\./\.\./\.\./index\.md\#type)* is a command that 738creates instances \-\- objects \-\- which belong to the type\. Most types define some 739number of *options* which can be set at creation time, and usually can be 740changed later\. 741 742Further, an *instance* is also a Tcl command\-\-a command that gives access to 743the operations which are defined for that abstract data type\. Conventionally, 744the operations are defined as subcommands of the instance command\. For example, 745to insert text into a Tk text widget, you use the text widget's __insert__ 746subcommand: 747 748 # Create a text widget and insert some text in it. 749 text .mytext -width 80 -height 24 750 .mytext insert end "Howdy!" 751 752In this example, __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ is the 753*[type](\.\./\.\./\.\./\.\./index\.md\#type)* command and __\.mytext__ is the 754*instance* command\. 755 756In Snit, object subcommands are generally called [INSTANCE 757METHODS](#section5)\. 758 759## <a name='subsection14'></a>What kinds of abstract data types does Snit provide? 760 761Snit allows you to define three kinds of abstract data type: 762 763 - __snit::type__ 764 765 - __snit::widget__ 766 767 - __snit::widgetadaptor__ 768 769## <a name='subsection15'></a>What is a snit::type? 770 771A __snit::type__ is a non\-GUI abstract data type, e\.g\., a stack or a queue\. 772__snit::type__s are defined using the __snit::type__ command\. For 773example, if you were designing a kennel management system for a dog breeder, 774you'd need a dog type\. 775 776 % snit::type dog { 777 # ... 778 } 779 ::dog 780 % 781 782This definition defines a new command \(__::dog__, in this case\) that can be 783used to define dog objects\. 784 785An instance of a __snit::type__ can have [INSTANCE METHODS](#section5), 786[INSTANCE VARIABLES](#section6), [OPTIONS](#section7), and 787[COMPONENTS](#section14)\. The type itself can have [TYPE 788METHODS](#section9), [TYPE VARIABLES](#section8), [TYPE 789COMPONENTS](#section15), and [PROCS](#section10)\. 790 791## <a name='subsection16'></a>What is a snit::widget?, the short story 792 793A __snit::widget__ is a Tk megawidget built using Snit; it is very similar 794to a __snit::type__\. See [WIDGETS](#section17)\. 795 796## <a name='subsection17'></a>What is a snit::widgetadaptor?, the short story 797 798A __snit::widgetadaptor__ uses Snit to wrap an existing widget type \(e\.g\., a 799Tk label\), modifying its interface to a lesser or greater extent\. It is very 800similar to a __snit::widget__\. See [WIDGET ADAPTORS](#section18)\. 801 802## <a name='subsection18'></a>How do I create an instance of a snit::type? 803 804You create an instance of a __snit::type__ by passing the new instance's 805name to the type's create method\. In the following example, we create a 806__dog__ object called __spot__\. 807 808 % snit::type dog { 809 # .... 810 } 811 ::dog 812 % dog create spot 813 ::spot 814 % 815 816In general, the __create__ method name can be omitted so long as the 817instance name doesn't conflict with any defined [TYPE METHODS](#section9)\. 818\(See [TYPE COMPONENTS](#section15) for the special case in which this 819doesn't work\.\) So the following example is identical to the previous example: 820 821 % snit::type dog { 822 # .... 823 } 824 ::dog 825 % dog spot 826 ::spot 827 % 828 829This document generally uses the shorter form\. 830 831If the __dog__ type defines [OPTIONS](#section7), these can usually be 832given defaults at creation time: 833 834 % snit::type dog { 835 option -breed mongrel 836 option -color brown 837 838 method bark {} { return "$self barks." } 839 } 840 ::dog 841 % dog create spot -breed dalmation -color spotted 842 ::spot 843 % spot cget -breed 844 dalmation 845 % spot cget -color 846 spotted 847 % 848 849Once created, the instance name now names a new Tcl command that is used to 850manipulate the object\. For example, the following code makes the dog bark: 851 852 % spot bark 853 ::spot barks. 854 % 855 856## <a name='subsection19'></a>How do I refer to an object indirectly? 857 858Some programmers prefer to save the object name in a variable, and reference it 859that way\. For example, 860 861 % snit::type dog { ... } 862 ::dog 863 % set d [dog spot -breed dalmation -color spotted] 864 ::spot 865 % $d cget -breed 866 dalmation 867 % $d bark 868 ::spot barks. 869 % 870 871If you prefer this style, you might prefer to have Snit generate the instance's 872name automatically\. 873 874## <a name='subsection20'></a>How can I generate the object name automatically? 875 876If you'd like Snit to generate an object name for you, use the __%AUTO%__ 877keyword as the requested name: 878 879 % snit::type dog { ... } 880 ::dog 881 % set d [dog %AUTO%] 882 ::dog2 883 % $d bark 884 ::dog2 barks. 885 % 886 887The __%AUTO%__ keyword can be embedded in a longer string: 888 889 % set d [dog obj_%AUTO%] 890 ::obj_dog4 891 % $d bark 892 ::obj_dog4 barks. 893 % 894 895## <a name='subsection21'></a>Can types be renamed? 896 897Tcl's __rename__ command renames other commands\. It's a common technique in 898Tcl to modify an existing command by renaming it and defining a new command with 899the original name; the new command usually calls the renamed command\. 900 901__snit::type__ commands, however, should never be renamed; to do so breaks 902the connection between the type and its objects\. 903 904## <a name='subsection22'></a>Can objects be renamed? 905 906Tcl's __rename__ command renames other commands\. It's a common technique in 907Tcl to modify an existing command by renaming it and defining a new command with 908the original name; the new command usually calls the renamed command\. 909 910All Snit objects \(including *widgets* and *widgetadaptors*\) can be renamed, 911though this flexibility has some consequences: 912 913 - In an instance method, the implicit argument __self__ will always 914 contain the object's current name, so instance methods can always call other 915 instance methods using __$self__\. 916 917 - If the object is renamed, however, then __$self__'s value will change\. 918 Therefore, don't use __$self__ for anything that will break if 919 __$self__ changes\. For example, don't pass a callback command to another 920 object like this: 921 922 .btn configure -command [list $self ButtonPress] 923 924 You'll get an error if __\.btn__ calls your command after your object is 925 renamed\. 926 927 - Instead, your object should define its callback command like this: 928 929 .btn configure -command [mymethod ButtonPress] 930 931 The __mymethod__ command returns code that will call the desired method 932 safely; the caller of the callback can add additional arguments to the end 933 of the command as usual\. 934 935 - Every object has a private namespace; the name of this namespace is 936 available in method bodies, etc\., as the value of the implicit argument 937 __selfns__\. This value is constant for the life of the object\. Use 938 __$selfns__ instead of __$self__ if you need a unique token to 939 identify the object\. 940 941 - When a __snit::widget__'s instance command is renamed, its Tk window 942 name remains the same \-\- and is still extremely important\. Consequently, the 943 Tk window name is available in method bodies as the value of the implicit 944 argument __win__\. This value is constant for the life of the object\. 945 When creating child windows, it's best to use __$win\.child__ rather than 946 __$self\.child__ as the name of the child window\. 947 948## <a name='subsection23'></a>How do I destroy a Snit object? 949 950Any Snit object of any type can be destroyed by renaming it to the empty string 951using the Tcl __rename__ command\. 952 953Snit megawidgets \(i\.e\., instances of __snit::widget__ and 954__snit::widgetadaptor__\) can be destroyed like any other widget: by using 955the Tk __destroy__ command on the widget or on one of its ancestors in the 956window hierarchy\. 957 958Every instance of a __snit::type__ has a __destroy__ method: 959 960 % snit::type dog { ... } 961 ::dog 962 % dog spot 963 ::spot 964 % spot bark 965 ::spot barks. 966 % spot destroy 967 % spot barks 968 invalid command name "spot" 969 % 970 971Finally, every Snit type has a type method called __destroy__; calling it 972destroys the type and all of its instances: 973 974 % snit::type dog { ... } 975 ::dog 976 % dog spot 977 ::spot 978 % spot bark 979 ::spot barks. 980 % dog destroy 981 % spot bark 982 invalid command name "spot" 983 % dog fido 984 invalid command name "dog" 985 % 986 987# <a name='section5'></a>INSTANCE METHODS 988 989## <a name='subsection24'></a>What is an instance method? 990 991An instance method is a procedure associated with a specific object and called 992as a subcommand of the object's command\. It is given free access to all of the 993object's type variables, instance variables, and so forth\. 994 995## <a name='subsection25'></a>How do I define an instance method? 996 997Instance methods are defined in the type definition using the 998__[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement\. Consider the 999following code that might be used to add dogs to a computer simulation: 1000 1001 % snit::type dog { 1002 method bark {} { 1003 return "$self barks." 1004 } 1005 1006 method chase {thing} { 1007 return "$self chases $thing." 1008 } 1009 } 1010 ::dog 1011 % 1012 1013A dog can bark, and it can chase things\. 1014 1015The __[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement looks just like 1016a normal Tcl __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, except that it 1017appears in a __snit::type__ definition\. Notice that every instance method 1018gets an implicit argument called __self__; this argument contains the 1019object's name\. \(There's more on implicit method arguments below\.\) 1020 1021## <a name='subsection26'></a>How does a client call an instance method? 1022 1023The method name becomes a subcommand of the object\. For example, let's put a 1024simulated dog through its paces: 1025 1026 % dog spot 1027 ::spot 1028 % spot bark 1029 ::spot barks. 1030 % spot chase cat 1031 ::spot chases cat. 1032 % 1033 1034## <a name='subsection27'></a>How does an instance method call another instance method? 1035 1036If method A needs to call method B on the same object, it does so just as a 1037client does: it calls method B as a subcommand of the object itself, using the 1038object name stored in the implicit argument __self__\. 1039 1040Suppose, for example, that our dogs never chase anything without barking at 1041them: 1042 1043 % snit::type dog { 1044 method bark {} { 1045 return "$self barks." 1046 } 1047 1048 method chase {thing} { 1049 return "$self chases $thing. [$self bark]" 1050 } 1051 } 1052 ::dog 1053 % dog spot 1054 ::spot 1055 % spot bark 1056 ::spot barks. 1057 % spot chase cat 1058 ::spot chases cat. ::spot barks. 1059 % 1060 1061## <a name='subsection28'></a>Are there any limitations on instance method names? 1062 1063Not really, so long as you avoid the standard instance method names: 1064__configure__, __configurelist__, __cget__, __destroy__, and 1065__info__\. Also, method names consisting of multiple words define 1066hierarchical methods\. 1067 1068## <a name='subsection29'></a>What is a hierarchical method? 1069 1070An object's methods are subcommands of the object's instance command\. 1071Hierarchical methods allow an object's methods to have subcommands of their own; 1072and these can in turn have subcommands, and so on\. This allows the programmer to 1073define a tree\-shaped command structure, such as is used by many of the Tk 1074widgets\-\-the subcommands of the Tk __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ 1075widget's __tag__ method are hierarchical methods\. 1076 1077## <a name='subsection30'></a>How do I define a hierarchical method? 1078 1079Define methods whose names consist of multiple words\. These words define the 1080hierarchy implicitly\. For example, the following code defines a __tag__ 1081method with subcommands __cget__ and __configure__: 1082 1083 snit::widget mytext { 1084 method {tag configure} {tag args} { ... } 1085 1086 method {tag cget} {tag option} {...} 1087 } 1088 1089Note that there is no explicit definition for the __tag__ method; it is 1090implicit in the definition of __tag configure__ and __tag cget__\. If you 1091tried to define __tag__ explicitly in this example, you'd get an error\. 1092 1093## <a name='subsection31'></a>How do I call hierarchical methods? 1094 1095As subcommands of subcommands\. 1096 1097 % mytext .text 1098 .text 1099 % .text tag configure redtext -foreground red -background black 1100 % .text tag cget redtext -foreground 1101 red 1102 % 1103 1104## <a name='subsection32'></a>How do I make an instance method private? 1105 1106It's often useful to define private methods, that is, instance methods intended 1107to be called only by other methods of the same object\. 1108 1109Snit doesn't implement any access control on instance methods, so all methods 1110are *de facto* public\. Conventionally, though, the names of public methods 1111begin with a lower\-case letter, and the names of private methods begin with an 1112upper\-case letter\. 1113 1114For example, suppose our simulated dogs only bark in response to other stimuli; 1115they never bark just for fun\. So the __bark__ method becomes __Bark__ to 1116indicate that it is private: 1117 1118 % snit::type dog { 1119 # Private by convention: begins with uppercase letter. 1120 method Bark {} { 1121 return "$self barks." 1122 } 1123 1124 method chase {thing} { 1125 return "$self chases $thing. [$self Bark]" 1126 } 1127 } 1128 ::dog 1129 % dog fido 1130 ::fido 1131 % fido chase cat 1132 ::fido chases cat. ::fido barks. 1133 % 1134 1135## <a name='subsection33'></a>Are there any limitations on instance method arguments? 1136 1137Method argument lists are defined just like normal Tcl 1138__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ argument lists; in particular, 1139they can include arguments with default values and the __args__ argument\. 1140 1141However, every method also has a number of implicit arguments provided by Snit 1142in addition to those explicitly defined\. The names of these implicit arguments 1143may not used to name explicit arguments\. 1144 1145## <a name='subsection34'></a>What implicit arguments are passed to each instance method? 1146 1147The arguments implicitly passed to every method are __type__, 1148__selfns__, __win__, and __self__\. 1149 1150## <a name='subsection35'></a>What is $type? 1151 1152The implicit argument __type__ contains the fully qualified name of the 1153object's type: 1154 1155 % snit::type thing { 1156 method mytype {} { 1157 return $type 1158 } 1159 } 1160 ::thing 1161 % thing something 1162 ::something 1163 % something mytype 1164 ::thing 1165 % 1166 1167## <a name='subsection36'></a>What is $self? 1168 1169The implicit argument __self__ contains the object's fully qualified name\. 1170 1171If the object's command is renamed, then __$self__ will change to match in 1172subsequent calls\. Thus, your code should not assume that __$self__ is 1173constant unless you know for sure that the object will never be renamed\. 1174 1175 % snit::type thing { 1176 method myself {} { 1177 return $self 1178 } 1179 } 1180 ::thing 1181 % thing mutt 1182 ::mutt 1183 % mutt myself 1184 ::mutt 1185 % rename mutt jeff 1186 % jeff myself 1187 ::jeff 1188 % 1189 1190## <a name='subsection37'></a>What is $selfns? 1191 1192Each Snit object has a private namespace in which to store its [INSTANCE 1193VARIABLES](#section6) and [OPTIONS](#section7)\. The implicit argument 1194__selfns__ contains the name of this namespace; its value never changes, and 1195is constant for the life of the object, even if the object's name changes: 1196 1197 % snit::type thing { 1198 method myNameSpace {} { 1199 return $selfns 1200 } 1201 } 1202 ::thing 1203 % thing jeff 1204 ::jeff 1205 % jeff myNameSpace 1206 ::thing::Snit_inst3 1207 % rename jeff mutt 1208 % mutt myNameSpace 1209 ::thing::Snit_inst3 1210 % 1211 1212The above example reveals how Snit names an instance's private namespace; 1213however, you should not write code that depends on the specific naming 1214convention, as it might change in future releases\. 1215 1216## <a name='subsection38'></a>What is $win? 1217 1218The implicit argument __win__ is defined for all Snit methods, though it 1219really makes sense only for those of [WIDGETS](#section17) and [WIDGET 1220ADAPTORS](#section18)\. __$win__ is simply the original name of the 1221object, whether it's been renamed or not\. For widgets and widgetadaptors, it is 1222also therefore the name of a Tk window\. 1223 1224When a __snit::widgetadaptor__ is used to modify the interface of a widget 1225or megawidget, it must rename the widget's original command and replace it with 1226its own\. 1227 1228Thus, using __win__ whenever the Tk window name is called for means that a 1229__snit::widget__ or __snit::widgetadaptor__ can be adapted by a 1230__snit::widgetadaptor__\. See [WIDGETS](#section17) for more 1231information\. 1232 1233## <a name='subsection39'></a>How do I pass an instance method as a callback? 1234 1235It depends on the context\. 1236 1237Suppose in my application I have a __dog__ object named __fido__, and I 1238want __fido__ to bark when a Tk button called __\.bark__ is pressed\. In 1239this case, I create the callback command in the usual way, using 1240__[list](\.\./\.\./\.\./\.\./index\.md\#list)__: 1241 1242 button .bark -text "Bark!" -command [list fido bark] 1243 1244In typical Tcl style, we use a callback to hook two independent components 1245together\. But suppose that the __dog__ object has a graphical interface and 1246owns the button itself? In this case, the __dog__ must pass one of its own 1247instance methods to the button it owns\. The obvious thing to do is this: 1248 1249 % snit::widget dog { 1250 constructor {args} { 1251 #... 1252 button $win.barkbtn -text "Bark!" -command [list $self bark] 1253 #... 1254 } 1255 } 1256 ::dog 1257 % 1258 1259\(Note that in this example, our __dog__ becomes a __snit::widget__, 1260because it has GUI behavior\. See [WIDGETS](#section17) for more\.\) Thus, if 1261we create a __dog__ called __\.spot__, it will create a Tk button called 1262__\.spot\.barkbtn__; when pressed, the button will call __$self bark__\. 1263 1264Now, this will work\-\-provided that __\.spot__ is never renamed to something 1265else\. But surely renaming widgets is abnormal? And so it is\-\-unless 1266__\.spot__ is the hull component of a __snit::widgetadaptor__\. If it is, 1267then it will be renamed, and __\.spot__ will become the name of the 1268__snit::widgetadaptor__ object\. When the button is pressed, the command 1269__$self bark__ will be handled by the __snit::widgetadaptor__, which 1270might or might not do the right thing\. 1271 1272There's a safer way to do it, and it looks like this: 1273 1274 % snit::widget dog { 1275 constructor {args} { 1276 #... 1277 button $win.barkbtn -text "Bark!" -command [mymethod bark] 1278 #... 1279 } 1280 } 1281 ::dog 1282 % 1283 1284The command __mymethod__ takes any number of arguments, and can be used like 1285__[list](\.\./\.\./\.\./\.\./index\.md\#list)__ to build up a callback command; 1286the only difference is that __mymethod__ returns a form of the command that 1287won't change even if the instance's name changes\. 1288 1289On the other hand, you might prefer to allow a widgetadaptor to override a 1290method such that your renamed widget will call the widgetadaptor's method 1291instead of its own\. In this case, using __\[list $self bark\]__ will do what 1292you want\.\.\.but this is a technique which should be used only in carefully 1293controlled circumstances\. 1294 1295## <a name='subsection40'></a>How do I delegate instance methods to a component? 1296 1297See [DELEGATION](#section16)\. 1298 1299# <a name='section6'></a>INSTANCE VARIABLES 1300 1301## <a name='subsection41'></a>What is an instance variable? 1302 1303An instance variable is a private variable associated with some particular Snit 1304object\. Instance variables can be scalars or arrays\. 1305 1306## <a name='subsection42'></a>How is a scalar instance variable defined? 1307 1308Scalar instance variables are defined in the type definition using the 1309__variable__ statement\. You can simply name it, or you can initialize it 1310with a value: 1311 1312 snit::type mytype { 1313 # Define variable "greeting" and initialize it with "Howdy!" 1314 variable greeting "Howdy!" 1315 } 1316 1317## <a name='subsection43'></a>How is an array instance variable defined? 1318 1319Array instance variables are also defined in the type definition using the 1320__variable__ command\. You can initialize them at the same time by specifying 1321the __\-array__ option: 1322 1323 snit::type mytype { 1324 # Define array variable "greetings" 1325 variable greetings -array { 1326 formal "Good Evening" 1327 casual "Howdy!" 1328 } 1329 } 1330 1331## <a name='subsection44'></a>What happens if I don't initialize an instance variable? 1332 1333Variables do not really exist until they are given values\. If you do not 1334initialize a variable when you define it, then you must be sure to assign a 1335value to it \(in the constructor, say, or in some method\) before you reference 1336it\. 1337 1338## <a name='subsection45'></a>Are there any limitations on instance variable names? 1339 1340Just a few\. 1341 1342First, every Snit object has a built\-in instance variable called 1343__options__, which should never be redefined\. 1344 1345Second, all names beginning with "Snit\_" are reserved for use by Snit internal 1346code\. 1347 1348Third, instance variable names containing the namespace delimiter \(__::__\) 1349are likely to cause great confusion\. 1350 1351## <a name='subsection46'></a>Do I need to declare my instance variables in my methods? 1352 1353No\. Once you've defined an instance variable in the type definition, it can be 1354used in any instance code \(instance methods, the constructor, and the 1355destructor\) without declaration\. This differs from normal Tcl practice, in which 1356all non\-local variables in a proc need to be declared\. 1357 1358There is a speed penalty to having all instance variables implicitly available 1359in all instance code\. Even though your code need not declare the variables 1360explicitly, Snit must still declare them, and that takes time\. If you have ten 1361instance variables, a method that uses none of them must still pay the 1362declaration penalty for all ten\. In most cases, the additional runtime cost is 1363negligible\. If extreme cases, you might wish to avoid it; there are two methods 1364for doing so\. 1365 1366The first is to define a single instance variable, an array, and store all of 1367your instance data in the array\. This way, you're only paying the declaration 1368penalty for one variable\-\-and you probably need the variable most of the time 1369anyway\. This method breaks down if your instance variables include multiple 1370arrays; in Tcl 8\.5, however, the __[dict](\.\./\.\./\.\./\.\./index\.md\#dict)__ 1371command might come to your rescue\. 1372 1373The second method is to declare your instance variables explicitly in your 1374instance code, while *not* including them in the type definition: 1375 1376 snit::type dog { 1377 constructor {} { 1378 variable mood 1379 1380 set mood happy 1381 } 1382 1383 method setmood {newMood} { 1384 variable mood 1385 1386 set mood $newMood 1387 } 1388 1389 method getmood {} { 1390 variable mood 1391 1392 return $mood 1393 } 1394 } 1395 1396This allows you to ensure that only the required variables are included in each 1397method, at the cost of longer code and run\-time errors when you forget to 1398declare a variable you need\. 1399 1400## <a name='subsection47'></a>How do I pass an instance variable's name to another object? 1401 1402In Tk, it's common to pass a widget a variable name; for example, Tk label 1403widgets have a __\-textvariable__ option which names the variable which will 1404contain the widget's text\. This allows the program to update the label's value 1405just by assigning a new value to the variable\. 1406 1407If you naively pass the instance variable name to the label widget, you'll be 1408confused by the result; Tk will assume that the name names a global variable\. 1409Instead, you need to provide a fully\-qualified variable name\. From within an 1410instance method or a constructor, you can fully qualify the variable's name 1411using the __myvar__ command: 1412 1413 snit::widget mywidget { 1414 variable labeltext "" 1415 1416 constructor {args} { 1417 # ... 1418 1419 label $win.label -textvariable [myvar labeltext] 1420 1421 # ... 1422 } 1423 } 1424 1425## <a name='subsection48'></a>How do I make an instance variable public? 1426 1427Practically speaking, you don't\. Instead, you'll implement public variables as 1428[OPTIONS](#section7)\. Alternatively, you can write [INSTANCE 1429METHODS](#section5) to set and get the variable's value\. 1430 1431# <a name='section7'></a>OPTIONS 1432 1433## <a name='subsection49'></a>What is an option? 1434 1435A type's options are the equivalent of what other object\-oriented languages 1436would call public member variables or properties: they are data values which can 1437be retrieved and \(usually\) set by the clients of an object\. 1438 1439Snit's implementation of options follows the Tk model fairly exactly, except 1440that __snit::type__ objects usually don't interact with [THE TK OPTION 1441DATABASE](#section19); __snit::widget__ and __snit::widgetadaptor__ 1442objects, on the other hand, always do\. 1443 1444## <a name='subsection50'></a>How do I define an option? 1445 1446Options are defined in the type definition using the __option__ statement\. 1447Consider the following type, to be used in an application that manages a list of 1448dogs for a pet store: 1449 1450 snit::type dog { 1451 option -breed -default mongrel 1452 option -color -default brown 1453 option -akc -default 0 1454 option -shots -default 0 1455 } 1456 1457According to this, a dog has four notable properties: a breed, a color, a flag 1458that says whether it's pedigreed with the American Kennel Club, and another flag 1459that says whether it has had its shots\. The default dog, evidently, is a brown 1460mutt\. 1461 1462There are a number of options you can specify when defining an option; if 1463__\-default__ is the only one, you can omit the word __\-default__ as 1464follows: 1465 1466 snit::type dog { 1467 option -breed mongrel 1468 option -color brown 1469 option -akc 0 1470 option -shots 0 1471 } 1472 1473If no __\-default__ value is specified, the option's default value will be 1474the empty string \(but see [THE TK OPTION DATABASE](#section19)\)\. 1475 1476The Snit man page refers to options like these as "locally defined" options\. 1477 1478## <a name='subsection51'></a>How can a client set options at object creation? 1479 1480The normal convention is that the client may pass any number of options and 1481their values after the object's name at object creation\. For example, the 1482__::dog__ command defined in the previous answer can now be used to create 1483individual dogs\. Any or all of the options may be set at creation time\. 1484 1485 % dog spot -breed beagle -color "mottled" -akc 1 -shots 1 1486 ::spot 1487 % dog fido -shots 1 1488 ::fido 1489 % 1490 1491So __::spot__ is a pedigreed beagle; __::fido__ is a typical mutt, but 1492his owners evidently take care of him, because he's had his shots\. 1493 1494*Note:* If the type defines a constructor, it can specify a different 1495object\-creation syntax\. See [CONSTRUCTORS](#section12) for more 1496information\. 1497 1498## <a name='subsection52'></a>How can a client retrieve an option's value? 1499 1500Retrieve option values using the __cget__ method: 1501 1502 % spot cget -color 1503 mottled 1504 % fido cget -breed 1505 mongrel 1506 % 1507 1508## <a name='subsection53'></a>How can a client set options after object creation? 1509 1510Any number of options may be set at one time using the __configure__ 1511instance method\. Suppose that closer inspection shows that ::fido is not a brown 1512mongrel, but rather a rare Arctic Boar Hound of a lovely dun color: 1513 1514 % fido configure -color dun -breed "Arctic Boar Hound" 1515 % fido cget -color 1516 dun 1517 % fido cget -breed 1518 Arctic Boar Hound 1519 1520Alternatively, the __configurelist__ method takes a list of options and 1521values; occasionally this is more convenient: 1522 1523 % set features [list -color dun -breed "Arctic Boar Hound"] 1524 -color dun -breed {Arctic Boar Hound} 1525 % fido configurelist $features 1526 % fido cget -color 1527 dun 1528 % fido cget -breed 1529 Arctic Boar Hound 1530 % 1531 1532In Tcl 8\.5, the __\*__ keyword can be used with __configure__ in this 1533case: 1534 1535 % set features [list -color dun -breed "Arctic Boar Hound"] 1536 -color dun -breed {Arctic Boar Hound} 1537 % fido configure {*}$features 1538 % fido cget -color 1539 dun 1540 % fido cget -breed 1541 Arctic Boar Hound 1542 % 1543 1544The results are the same\. 1545 1546## <a name='subsection54'></a>How should an instance method access an option value? 1547 1548There are two ways an instance method can set and retrieve an option's value\. 1549One is to use the __configure__ and __cget__ methods, as shown below\. 1550 1551 % snit::type dog { 1552 option -weight 10 1553 1554 method gainWeight {} { 1555 set wt [$self cget -weight] 1556 incr wt 1557 $self configure -weight $wt 1558 } 1559 } 1560 ::dog 1561 % dog fido 1562 ::fido 1563 % fido cget -weight 1564 10 1565 % fido gainWeight 1566 % fido cget -weight 1567 11 1568 % 1569 1570Alternatively, Snit provides a built\-in array instance variable called 1571__options__\. The indices are the option names; the values are the option 1572values\. The method __gainWeight__ can thus be rewritten as follows: 1573 1574 method gainWeight {} { 1575 incr options(-weight) 1576 } 1577 1578As you can see, using the __options__ variable involves considerably less 1579typing and is the usual way to do it\. But if you use __\-configuremethod__ or 1580__\-cgetmethod__ \(described in the following answers\), you might wish to use 1581the __configure__ and __cget__ methods anyway, just so that any special 1582processing you've implemented is sure to get done\. Also, if the option is 1583delegated to a component then __configure__ and __cget__ are the only 1584way to access it without accessing the component directly\. See 1585[DELEGATION](#section16) for more information\. 1586 1587## <a name='subsection55'></a>How can I make an option read\-only? 1588 1589Define the option with __\-readonly yes__\. 1590 1591Suppose you've got an option that determines how instances of your type are 1592constructed; it must be set at creation time, after which it's constant\. For 1593example, a dog never changes its breed; it might or might not have had its 1594shots, and if not can have them at a later time\. __\-breed__ should be 1595read\-only, but __\-shots__ should not be\. 1596 1597 % snit::type dog { 1598 option -breed -default mongrel -readonly yes 1599 option -shots -default no 1600 } 1601 ::dog 1602 % dog fido -breed retriever 1603 ::fido 1604 % fido configure -shots yes 1605 % fido configure -breed terrier 1606 option -breed can only be set at instance creation 1607 % 1608 1609## <a name='subsection56'></a>How can I catch accesses to an option's value? 1610 1611Define a __\-cgetmethod__ for the option\. 1612 1613## <a name='subsection57'></a>What is a \-cgetmethod? 1614 1615A __\-cgetmethod__ is a method that's called whenever the related option's 1616value is queried via the __cget__ instance method\. The handler can compute 1617the option's value, retrieve it from a database, or do anything else you'd like 1618it to do\. 1619 1620Here's what the default behavior would look like if written using a 1621__\-cgetmethod__: 1622 1623 snit::type dog { 1624 option -color -default brown -cgetmethod GetOption 1625 1626 method GetOption {option} { 1627 return $options($option) 1628 } 1629 } 1630 1631Any instance method can be used, provided that it takes one argument, the name 1632of the option whose value is to be retrieved\. 1633 1634## <a name='subsection58'></a>How can I catch changes to an option's value? 1635 1636Define a __\-configuremethod__ for the option\. 1637 1638## <a name='subsection59'></a>What is a \-configuremethod? 1639 1640A __\-configuremethod__ is a method that's called whenever the related option 1641is given a new value via the __configure__ or __configurelist__ instance 1642methods\. The method can pass the value on to some other object, store it in a 1643database, or do anything else you'd like it to do\. 1644 1645Here's what the default configuration behavior would look like if written using 1646a __\-configuremethod__: 1647 1648 snit::type dog { 1649 option -color -default brown -configuremethod SetOption 1650 1651 method SetOption {option value} { 1652 set options($option) $value 1653 } 1654 } 1655 1656Any instance method can be used, provided that it takes two arguments, the name 1657of the option and the new value\. 1658 1659Note that if your method doesn't store the value in the __options__ array, 1660the __options__ array won't get updated\. 1661 1662## <a name='subsection60'></a>How can I validate an option's value? 1663 1664Define a __\-validatemethod__\. 1665 1666## <a name='subsection61'></a>What is a \-validatemethod? 1667 1668A __\-validatemethod__ is a method that's called whenever the related option 1669is given a new value via the __configure__ or __configurelist__ instance 1670methods\. It's the method's responsibility to determine whether the new value is 1671valid, and throw an error if it isn't\. The __\-validatemethod__, if any, is 1672called before the value is stored in the __options__ array; in particular, 1673it's called before the __\-configuremethod__, if any\. 1674 1675For example, suppose an option always takes a Boolean value\. You can ensure that 1676the value is in fact a valid Boolean like this: 1677 1678 % snit::type dog { 1679 option -shots -default no -validatemethod BooleanOption 1680 1681 method BooleanOption {option value} { 1682 if {![string is boolean -strict $value]} { 1683 error "expected a boolean value, got \"$value\"" 1684 } 1685 } 1686 } 1687 ::dog 1688 % dog fido 1689 % fido configure -shots yes 1690 % fido configure -shots NotABooleanValue 1691 expected a boolean value, got "NotABooleanValue" 1692 % 1693 1694Note that the same __\-validatemethod__ can be used to validate any number of 1695boolean options\. 1696 1697Any method can be a __\-validatemethod__ provided that it takes two 1698arguments, the option name and the new option value\. 1699 1700# <a name='section8'></a>TYPE VARIABLES 1701 1702## <a name='subsection62'></a>What is a type variable? 1703 1704A type variable is a private variable associated with a Snit type rather than 1705with a particular instance of the type\. In C\+\+ and Java, the term *static 1706member variable* is used for the same notion\. Type variables can be scalars or 1707arrays\. 1708 1709## <a name='subsection63'></a>How is a scalar type variable defined? 1710 1711Scalar type variables are defined in the type definition using the 1712__typevariable__ statement\. You can simply name it, or you can initialize it 1713with a value: 1714 1715 snit::type mytype { 1716 # Define variable "greeting" and initialize it with "Howdy!" 1717 typevariable greeting "Howdy!" 1718 } 1719 1720Every object of type __mytype__ now has access to a single variable called 1721__greeting__\. 1722 1723## <a name='subsection64'></a>How is an array\-valued type variable defined? 1724 1725Array\-valued type variables are also defined using the __typevariable__ 1726command; to initialize them, include the __\-array__ option: 1727 1728 snit::type mytype { 1729 # Define typearray variable "greetings" 1730 typevariable greetings -array { 1731 formal "Good Evening" 1732 casual "Howdy!" 1733 } 1734 } 1735 1736## <a name='subsection65'></a>What happens if I don't initialize a type variable? 1737 1738Variables do not really exist until they are given values\. If you do not 1739initialize a variable when you define it, then you must be sure to assign a 1740value to it \(in the type constructor, say\) before you reference it\. 1741 1742## <a name='subsection66'></a>Are there any limitations on type variable names? 1743 1744Type variable names have the same restrictions as the names of [INSTANCE 1745VARIABLES](#section6) do\. 1746 1747## <a name='subsection67'></a>Do I need to declare my type variables in my methods? 1748 1749No\. Once you've defined a type variable in the type definition, it can be used 1750in [INSTANCE METHODS](#section5) or [TYPE METHODS](#section9) without 1751declaration\. This differs from normal Tcl practice, in which all non\-local 1752variables in a proc need to be declared\. 1753 1754Type variables are subject to the same speed/readability tradeoffs as instance 1755variables; see [Do I need to declare my instance variables in my 1756methods?](#subsection46) 1757 1758## <a name='subsection68'></a>How do I pass a type variable's name to another object? 1759 1760In Tk, it's common to pass a widget a variable name; for example, Tk label 1761widgets have a __\-textvariable__ option which names the variable which will 1762contain the widget's text\. This allows the program to update the label's value 1763just by assigning a new value to the variable\. 1764 1765If you naively pass a type variable name to the label widget, you'll be confused 1766by the result; Tk will assume that the name names a global variable\. Instead, 1767you need to provide a fully\-qualified variable name\. From within an instance 1768method or a constructor, you can fully qualify the type variable's name using 1769the __mytypevar__ command: 1770 1771 snit::widget mywidget { 1772 typevariable labeltext "" 1773 1774 constructor {args} { 1775 # ... 1776 1777 label $win.label -textvariable [mytypevar labeltext] 1778 1779 # ... 1780 } 1781 } 1782 1783## <a name='subsection69'></a>How do I make a type variable public? 1784 1785There are two ways to do this\. The preferred way is to write a pair of [TYPE 1786METHODS](#section9) to set and query the type variable's value\. 1787 1788Type variables are stored in the type's namespace, which has the same name as 1789the type itself\. Thus, you can also publicize the type variable's name in your 1790documentation so that clients can access it directly\. For example, 1791 1792 snit::type mytype { 1793 typevariable myvariable 1794 } 1795 1796 set ::mytype::myvariable "New Value" 1797 1798# <a name='section9'></a>TYPE METHODS 1799 1800## <a name='subsection70'></a>What is a type method? 1801 1802A type method is a procedure associated with the type itself rather than with 1803any specific instance of the type, and called as a subcommand of the type 1804command\. 1805 1806## <a name='subsection71'></a>How do I define a type method? 1807 1808Type methods are defined in the type definition using the __typemethod__ 1809statement: 1810 1811 snit::type dog { 1812 # List of pedigreed dogs 1813 typevariable pedigreed 1814 1815 typemethod pedigreedDogs {} { 1816 return $pedigreed 1817 } 1818 } 1819 1820Suppose the __dog__ type maintains a list of the names of the dogs that have 1821pedigrees\. The __pedigreedDogs__ type method returns this list\. 1822 1823The __typemethod__ statement looks just like a normal Tcl 1824__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, except that it appears in a 1825__snit::type__ definition\. Notice that every type method gets an implicit 1826argument called __type__, which contains the fully\-qualified type name\. 1827 1828## <a name='subsection72'></a>How does a client call a type method? 1829 1830The type method name becomes a subcommand of the type's command\. For example, 1831assuming that the constructor adds each pedigreed dog to the list of 1832__pedigreedDogs__, 1833 1834 snit::type dog { 1835 option -pedigreed 0 1836 1837 # List of pedigreed dogs 1838 typevariable pedigreed 1839 1840 typemethod pedigreedDogs {} { 1841 return $pedigreed 1842 } 1843 1844 # ... 1845 } 1846 1847 dog spot -pedigreed 1 1848 dog fido 1849 1850 foreach dog [dog pedigreedDogs] { ... } 1851 1852## <a name='subsection73'></a>Are there any limitations on type method names? 1853 1854Not really, so long as you avoid the standard type method names: __create__, 1855__destroy__, and __info__\. 1856 1857## <a name='subsection74'></a>How do I make a type method private? 1858 1859It's sometimes useful to define private type methods, that is, type methods 1860intended to be called only by other type or instance methods of the same object\. 1861 1862Snit doesn't implement any access control on type methods; by convention, the 1863names of public methods begin with a lower\-case letter, and the names of private 1864methods begin with an upper\-case letter\. 1865 1866Alternatively, a Snit __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ can be used 1867as a private type method; see [PROCS](#section10)\. 1868 1869## <a name='subsection75'></a>Are there any limitations on type method arguments? 1870 1871Method argument lists are defined just like normal Tcl proc argument lists; in 1872particular, they can include arguments with default values and the __args__ 1873argument\. 1874 1875However, every type method is called with an implicit argument called 1876__type__ that contains the name of the type command\. In addition, type 1877methods should by convention avoid using the names of the arguments implicitly 1878defined for [INSTANCE METHODS](#section5)\. 1879 1880## <a name='subsection76'></a>How does an instance or type method call a type method? 1881 1882If an instance or type method needs to call a type method, it should use 1883__$type__ to do so: 1884 1885 snit::type dog { 1886 1887 typemethod pedigreedDogs {} { ... } 1888 1889 typemethod printPedigrees {} { 1890 foreach obj [$type pedigreedDogs] { ... } 1891 } 1892 } 1893 1894## <a name='subsection77'></a>How do I pass a type method as a callback? 1895 1896It's common in Tcl to pass a snippet of code to another object, for it to call 1897later\. Because types cannot be renamed, you can just use the type name, or, if 1898the callback is registered from within a type method, __type__\. For example, 1899suppose we want to print a list of pedigreed dogs when a Tk button is pushed: 1900 1901 button .btn -text "Pedigrees" -command [list dog printPedigrees] 1902 pack .btn 1903 1904Alternatively, from a method or type method you can use the __mytypemethod__ 1905command, just as you would use __mymethod__ to define a callback command for 1906[INSTANCE METHODS](#section5)\. 1907 1908## <a name='subsection78'></a>Can type methods be hierarchical? 1909 1910Yes, you can define hierarchical type methods in just the same way as you can 1911define hierarchical instance methods\. See [INSTANCE METHODS](#section5) for 1912more\. 1913 1914# <a name='section10'></a>PROCS 1915 1916## <a name='subsection79'></a>What is a proc? 1917 1918A Snit __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ is really just a Tcl proc 1919defined within the type's namespace\. You can use procs for private code that 1920isn't related to any particular instance\. 1921 1922## <a name='subsection80'></a>How do I define a proc? 1923 1924Procs are defined by including a __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ 1925statement in the type definition: 1926 1927 snit::type mytype { 1928 # Pops and returns the first item from the list stored in the 1929 # listvar, updating the listvar 1930 proc pop {listvar} { ... } 1931 1932 # ... 1933 } 1934 1935## <a name='subsection81'></a>Are there any limitations on proc names? 1936 1937Any name can be used, so long as it does not begin with __Snit\___; names 1938beginning with __Snit\___ are reserved for Snit's own use\. However, the wise 1939programmer will avoid __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ names 1940\(__[set](\.\./\.\./\.\./\.\./index\.md\#set)__, 1941__[list](\.\./\.\./\.\./\.\./index\.md\#list)__, __if__, etc\.\) that would 1942shadow standard Tcl command names\. 1943 1944__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__ names, being private, should begin 1945with a capital letter according to convention; however, as there are typically 1946no public __[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__s in the type's namespace 1947it doesn't matter much either way\. 1948 1949## <a name='subsection82'></a>How does a method call a proc? 1950 1951Just like it calls any Tcl command\. For example, 1952 1953 snit::type mytype { 1954 # Pops and returns the first item from the list stored in the 1955 # listvar, updating the listvar 1956 proc pop {listvar} { ... } 1957 1958 variable requestQueue {} 1959 1960 # Get one request from the queue and process it. 1961 method processRequest {} { 1962 set req [pop requestQueue] 1963 } 1964 } 1965 1966## <a name='subsection83'></a>How can I pass a proc to another object as a callback? 1967 1968The __myproc__ command returns a callback command for the 1969__[proc](\.\./\.\./\.\./\.\./index\.md\#proc)__, just as __mymethod__ does for 1970a method\. 1971 1972# <a name='section11'></a>TYPE CONSTRUCTORS 1973 1974## <a name='subsection84'></a>What is a type constructor? 1975 1976A type constructor is a body of code that initializes the type as a whole, 1977rather like a C\+\+ static initializer\. The body of a type constructor is executed 1978once when the type is defined, and never again\. 1979 1980A type can have at most one type constructor\. 1981 1982## <a name='subsection85'></a>How do I define a type constructor? 1983 1984A type constructor is defined by using the __typeconstructor__ statement in 1985the type definition\. For example, suppose the type uses an array\-valued type 1986variable as a look\-up table, and the values in the array have to be computed at 1987start\-up\. 1988 1989 % snit::type mytype { 1990 typevariable lookupTable 1991 1992 typeconstructor { 1993 array set lookupTable {key value...} 1994 } 1995 } 1996 1997# <a name='section12'></a>CONSTRUCTORS 1998 1999## <a name='subsection86'></a>What is a constructor? 2000 2001In object\-oriented programming, an object's constructor is responsible for 2002initializing the object completely at creation time\. The constructor receives 2003the list of options passed to the __snit::type__ command's __create__ 2004method and can then do whatever it likes\. That might include computing instance 2005variable values, reading data from files, creating other objects, updating type 2006and instance variables, and so forth\. 2007 2008The constructor's return value is ignored \(unless it's an error, of course\)\. 2009 2010## <a name='subsection87'></a>How do I define a constructor? 2011 2012A constructor is defined by using the __constructor__ statement in the type 2013definition\. Suppose that it's desired to keep a list of all pedigreed dogs\. The 2014list can be maintained in a type variable and retrieved by a type method\. 2015Whenever a dog is created, it can add itself to the list\-\-provided that it's 2016registered with the American Kennel Club\. 2017 2018 % snit::type dog { 2019 option -akc 0 2020 2021 typevariable akcList {} 2022 2023 constructor {args} { 2024 $self configurelist $args 2025 2026 if {$options(-akc)} { 2027 lappend akcList $self 2028 } 2029 } 2030 2031 typemethod akclist {} { 2032 return $akcList 2033 } 2034 } 2035 ::dog 2036 % dog spot -akc 1 2037 ::spot 2038 % dog fido 2039 ::fido 2040 % dog akclist 2041 ::spot 2042 % 2043 2044## <a name='subsection88'></a>What does the default constructor do? 2045 2046If you don't provide a constructor explicitly, you get the default constructor, 2047which is identical to the explicitly\-defined constructor shown here: 2048 2049 snit::type dog { 2050 constructor {args} { 2051 $self configurelist $args 2052 } 2053 } 2054 2055When the constructor is called, __args__ will be set to the list of 2056arguments that follow the object's name\. The constructor is allowed to interpret 2057this list any way it chooses; the normal convention is to assume that it's a 2058list of option names and values, as shown in the example above\. If you simply 2059want to save the option values, you should use the __configurelist__ method, 2060as shown\. 2061 2062## <a name='subsection89'></a>Can I choose a different set of arguments for the constructor? 2063 2064Yes, you can\. For example, suppose we wanted to be sure that the breed was 2065explicitly stated for every dog at creation time, and couldn't be changed 2066thereafter\. One way to do that is as follows: 2067 2068 % snit::type dog { 2069 variable breed 2070 2071 option -color brown 2072 option -akc 0 2073 2074 constructor {theBreed args} { 2075 set breed $theBreed 2076 $self configurelist $args 2077 } 2078 2079 method breed {} { return $breed } 2080 } 2081 ::dog 2082 % dog spot dalmatian -color spotted -akc 1 2083 ::spot 2084 % spot breed 2085 dalmatian 2086 2087The drawback is that this syntax is non\-standard, and may limit the 2088compatibility of your new type with other people's code\. For example, Snit 2089assumes that it can create [COMPONENTS](#section14) using the standard 2090creation syntax\. 2091 2092## <a name='subsection90'></a>Are there any limitations on constructor arguments? 2093 2094Constructor argument lists are subject to the same limitations as those on 2095instance method argument lists\. It has the same implicit arguments, and can 2096contain default values and the __args__ argument\. 2097 2098## <a name='subsection91'></a>Is there anything special about writing the constructor? 2099 2100Yes\. Writing the constructor can be tricky if you're delegating options to 2101components, and there are specific issues relating to __snit::widget__s and 2102__snit::widgetadaptor__s\. See [DELEGATION](#section16), 2103[WIDGETS](#section17), [WIDGET ADAPTORS](#section18), and [THE TK 2104OPTION DATABASE](#section19)\. 2105 2106# <a name='section13'></a>DESTRUCTORS 2107 2108## <a name='subsection92'></a>What is a destructor? 2109 2110A destructor is a special kind of method that's called when an object is 2111destroyed\. It's responsible for doing any necessary clean\-up when the object 2112goes away: destroying [COMPONENTS](#section14), closing files, and so 2113forth\. 2114 2115## <a name='subsection93'></a>How do I define a destructor? 2116 2117Destructors are defined by using the __destructor__ statement in the type 2118definition\. 2119 2120Suppose we're maintaining a list of pedigreed dogs; then we'll want to remove 2121dogs from it when they are destroyed\. 2122 2123 snit::type dog { 2124 option -akc 0 2125 2126 typevariable akcList {} 2127 2128 constructor {args} { 2129 $self configurelist $args 2130 2131 if {$options(-akc)} { 2132 lappend akcList $self 2133 } 2134 } 2135 2136 destructor { 2137 set ndx [lsearch $akcList $self] 2138 2139 if {$ndx != -1} { 2140 set akcList [lreplace $akcList $ndx $ndx] 2141 } 2142 } 2143 2144 typemethod akclist {} { 2145 return $akcList 2146 } 2147 } 2148 2149## <a name='subsection94'></a>Are there any limitations on destructor arguments? 2150 2151Yes; a destructor has no explicit arguments\. 2152 2153## <a name='subsection95'></a>What implicit arguments are passed to the destructor? 2154 2155The destructor gets the same implicit arguments that are passed to [INSTANCE 2156METHODS](#section5): __type__, __selfns__, __win__, and 2157__self__\. 2158 2159## <a name='subsection96'></a>Must components be destroyed explicitly? 2160 2161Yes and no\. 2162 2163Any Tk widgets created by a __snit::widget__ or __snit::widgetadaptor__ 2164will be destroyed automatically by Tk when the megawidget is destroyed, in 2165keeping with normal Tk behavior \(destroying a parent widget destroys the whole 2166tree\)\. 2167 2168Components of normal __snit::types__, on the other hand, are never destroyed 2169automatically, nor are non\-widget components of Snit megawidgets\. If your object 2170creates them in its constructor, then it should generally destroy them in its 2171destructor\. 2172 2173## <a name='subsection97'></a>Is there any special about writing a destructor? 2174 2175Yes\. If an object's constructor throws an error, the object's destructor will be 2176called to clean up; this means that the object might not be completely 2177constructed when the destructor is called\. This can cause the destructor to 2178throw its own error; the result is usually misleading, confusing, and unhelpful\. 2179Consequently, it's important to write your destructor so that it's fail\-safe\. 2180 2181For example, a __dog__ might create a __tail__ component; the component 2182will need to be destroyed\. But suppose there's an error while processing the 2183creation options\-\-the destructor will be called, and there will be no 2184__tail__ to destroy\. The simplest solution is generally to catch and ignore 2185any errors while destroying components\. 2186 2187 snit::type dog { 2188 component tail 2189 2190 constructor {args} { 2191 $self configurelist $args 2192 2193 set tail [tail %AUTO%] 2194 } 2195 2196 destructor { 2197 catch {$tail destroy} 2198 } 2199 } 2200 2201# <a name='section14'></a>COMPONENTS 2202 2203## <a name='subsection98'></a>What is a component? 2204 2205Often an object will create and manage a number of other objects\. A Snit 2206megawidget, for example, will often create a number of Tk widgets\. These objects 2207are part of the main object; it is composed of them, so they are called 2208components of the object\. 2209 2210But Snit also has a more precise meaning for [COMPONENT](#section14)\. The 2211components of a Snit object are those objects to which methods or options can be 2212delegated\. \(See [DELEGATION](#section16) for more information about 2213delegation\.\) 2214 2215## <a name='subsection99'></a>How do I declare a component? 2216 2217First, you must decide what role a component plays within your object, and give 2218the role a name\. Then, you declare the component using its role name and the 2219__component__ statement\. The __component__ statement declares an 2220*instance variable* which is used to store the component's command name when 2221the component is created\. 2222 2223For example, suppose your __dog__ object creates a __tail__ object \(the 2224better to wag with, no doubt\): 2225 2226 snit::type dog { 2227 component mytail 2228 2229 constructor {args} { 2230 # Create and save the component's command 2231 set mytail [tail %AUTO% -partof $self] 2232 $self configurelist $args 2233 } 2234 2235 method wag {} { 2236 $mytail wag 2237 } 2238 } 2239 2240As shown here, it doesn't matter what the __tail__ object's real name is; 2241the __dog__ object refers to it by its component name\. 2242 2243The above example shows one way to delegate the __wag__ method to the 2244__mytail__ component; see [DELEGATION](#section16) for an easier way\. 2245 2246## <a name='subsection100'></a>How is a component named? 2247 2248A component has two names\. The first name is that of the component variable; 2249this represents the role the component object plays within the Snit object\. This 2250is the component name proper, and is the name used to refer to the component 2251within Snit code\. The second name is the name of the actual component object 2252created by the Snit object's constructor\. This second name is always a Tcl 2253command name, and is referred to as the component's object name\. 2254 2255In the example in the previous question, the component name is __mytail__; 2256the __mytail__ component's object name is chosen automatically by Snit since 2257__%AUTO%__ was used when the component object was created\. 2258 2259## <a name='subsection101'></a>Are there any limitations on component names? 2260 2261Yes\. __snit::widget__ and __snit::widgetadaptor__ objects have a special 2262component called the __hull__ component; thus, the name __hull__ should 2263be used for no other purpose\. 2264 2265Otherwise, since component names are in fact instance variable names they must 2266follow the rules for [INSTANCE VARIABLES](#section6)\. 2267 2268## <a name='subsection102'></a>What is an owned component? 2269 2270An *owned* component is a component whose object command's lifetime is 2271controlled by the __snit::type__ or __snit::widget__\. 2272 2273As stated above, a component is an object to which our object can delegate 2274methods or options\. Under this definition, our object will usually create its 2275component objects, but not necessarily\. Consider the following: a dog object has 2276a tail component; but tail knows that it's part of the dog: 2277 2278 snit::type dog { 2279 component mytail 2280 2281 constructor {args} { 2282 set mytail [tail %AUTO% -partof $self] 2283 $self configurelist $args 2284 } 2285 2286 destructor { 2287 catch {$mytail destroy} 2288 } 2289 2290 delegate method wagtail to mytail as wag 2291 2292 method bark {} { 2293 return "$self barked." 2294 } 2295 } 2296 2297 snit::type tail { 2298 component mydog 2299 option -partof -readonly yes 2300 2301 constructor {args} { 2302 $self configurelist $args 2303 set mydog $options(-partof) 2304 } 2305 2306 method wag {} { 2307 return "Wag, wag." 2308 } 2309 2310 method pull {} { 2311 $mydog bark 2312 } 2313 } 2314 2315Thus, if you ask a dog to wag its tail, it tells its tail to wag; and if you 2316pull the dog's tail, the tail tells the dog to bark\. In this scenario, the tail 2317is a component of the dog, and the dog is a component of the tail, but the dog 2318owns the tail and not the other way around\. 2319 2320## <a name='subsection103'></a>What does the install command do? 2321 2322The __install__ command creates an owned component using a specified 2323command, and assigns the result to the component's instance variable\. For 2324example: 2325 2326 snit::type dog { 2327 component mytail 2328 2329 constructor {args} { 2330 # set mytail [tail %AUTO% -partof $self] 2331 install mytail using tail %AUTO% -partof $self 2332 $self configurelist $args 2333 } 2334 } 2335 2336In a __snit::type__'s code, the __install__ command shown above is 2337equivalent to the __set mytail__ command that's commented out\. In a 2338__snit::widget__'s or __snit::widgetadaptor__'s, code, however, the 2339__install__ command also queries [THE TK OPTION DATABASE](#section19) 2340and initializes the new component's options accordingly\. For consistency, it's a 2341good idea to get in the habit of using __install__ for all owned components\. 2342 2343## <a name='subsection104'></a>Must owned components be created in the constructor? 2344 2345No, not necessarily\. In fact, there's no reason why an object can't destroy and 2346recreate a component multiple times over its own lifetime\. 2347 2348## <a name='subsection105'></a>Are there any limitations on component object names? 2349 2350Yes\. 2351 2352Component objects which are Tk widgets or megawidgets must have valid Tk window 2353names\. 2354 2355Component objects which are not widgets or megawidgets must have fully\-qualified 2356command names, i\.e\., names which include the full namespace of the command\. Note 2357that Snit always creates objects with fully qualified names\. 2358 2359Next, the object names of components and owned by your object must be unique\. 2360This is no problem for widget components, since widget names are always unique; 2361but consider the following code: 2362 2363 snit::type tail { ... } 2364 2365 snit::type dog { 2366 delegate method wag to mytail 2367 2368 constructor {} { 2369 install mytail using tail mytail 2370 } 2371 } 2372 2373This code uses the component name, __mytail__, as the component object name\. 2374This is not good, and here's why: Snit instance code executes in the Snit type's 2375namespace\. In this case, the __mytail__ component is created in the 2376__::dog::__ namespace, and will thus have the name __::dog::mytail__\. 2377 2378Now, suppose you create two dogs\. Both dogs will attempt to create a tail called 2379__::dog::mytail__\. The first will succeed, and the second will fail, since 2380Snit won't let you create an object if its name is already a command\. Here are 2381two ways to avoid this situation: 2382 2383First, if the component type is a __snit::type__ you can specify 2384__%AUTO%__ as its name, and be guaranteed to get a unique name\. This is the 2385safest thing to do: 2386 2387 install mytail using tail %AUTO% 2388 2389If the component type isn't a __snit::type__ you can create the component in 2390the object's instance namespace: 2391 2392 install mytail using tail ${selfns}::mytail 2393 2394Make sure you pick a unique name within the instance namespace\. 2395 2396## <a name='subsection106'></a>Must I destroy the components I own? 2397 2398That depends\. When a parent widget is destroyed, all child widgets are destroyed 2399automatically\. Thus, if your object is a __snit::widget__ or 2400__snit::widgetadaptor__ you don't need to destroy any components that are 2401widgets, because they will generally be children or descendants of your 2402megawidget\. 2403 2404If your object is an instance of __snit::type__, though, none of its owned 2405components will be destroyed automatically, nor will be non\-widget components of 2406a __snit::widget__ be destroyed automatically\. All such owned components 2407must be destroyed explicitly, or they won't be destroyed at all\. 2408 2409## <a name='subsection107'></a>Can I expose a component's object command as part of my interface? 2410 2411Yes, and there are two ways to do it\. The most appropriate way is usually to use 2412[DELEGATION](#section16)\. Delegation allows you to pass the options and 2413methods you specify along to particular components\. This effectively hides the 2414components from the users of your type, and ensures good encapsulation\. 2415 2416However, there are times when it's appropriate, not to mention simpler, just to 2417make the entire component part of your type's public interface\. 2418 2419## <a name='subsection108'></a>How do I expose a component's object command? 2420 2421When you declare the component, specify the __component__ statement's 2422__\-public__ option\. The value of this option is the name of a method which 2423will be delegated to your component's object command\. 2424 2425For example, supposed you've written a combobox megawidget which owns a listbox 2426widget, and you want to make the listbox's entire interface public\. You can do 2427it like this: 2428 2429 snit::widget combobox { 2430 component listbox -public listbox 2431 2432 constructor {args} { 2433 install listbox using listbox $win.listbox .... 2434 } 2435 } 2436 2437 combobox .mycombo 2438 .mycombo listbox configure -width 30 2439 2440Your comobox widget, __\.mycombo__, now has a __listbox__ method which 2441has all of the same subcommands as the listbox widget itself\. Thus, the above 2442code sets the listbox component's width to 30\. 2443 2444Usually you'll let the method name be the same as the component name; however, 2445you can name it anything you like\. 2446 2447# <a name='section15'></a>TYPE COMPONENTS 2448 2449## <a name='subsection109'></a>What is a type component? 2450 2451A type component is a component that belongs to the type itself instead of to a 2452particular instance of the type\. The relationship between components and type 2453components is the same as the relationship between [INSTANCE 2454VARIABLES](#section6) and [TYPE VARIABLES](#section8)\. Both [INSTANCE 2455METHODS](#section5) and [TYPE METHODS](#section9) can be delegated to 2456type components\. 2457 2458Once you understand [COMPONENTS](#section14) and 2459[DELEGATION](#section16), type components are just more of the same\. 2460 2461## <a name='subsection110'></a>How do I declare a type component? 2462 2463Declare a type component using the __typecomponent__ statement\. It takes the 2464same options \(__\-inherit__ and __\-public__\) as the __component__ 2465statement does, and defines a type variable to hold the type component's object 2466command\. 2467 2468Suppose in your model you've got many dogs, but only one veterinarian\. You might 2469make the veterinarian a type component\. 2470 2471 snit::type veterinarian { ... } 2472 2473 snit::type dog { 2474 typecomponent vet 2475 2476 # ... 2477 } 2478 2479## <a name='subsection111'></a>How do I install a type component? 2480 2481Just use the __[set](\.\./\.\./\.\./\.\./index\.md\#set)__ command to assign the 2482component's object command to the type component\. Because types \(even 2483__snit::widget__ types\) are not widgets, and do not have options anyway, the 2484extra features of the __install__ command are not needed\. 2485 2486You'll usually install type components in the type constructor, as shown here: 2487 2488 snit::type veterinarian { ... } 2489 2490 snit::type dog { 2491 typecomponent vet 2492 2493 typeconstructor { 2494 set vet [veterinarian %AUTO%] 2495 } 2496 } 2497 2498## <a name='subsection112'></a>Are there any limitations on type component names? 2499 2500Yes, the same as on [INSTANCE VARIABLES](#section6), [TYPE 2501VARIABLES](#section8), and normal [COMPONENTS](#section14)\. 2502 2503# <a name='section16'></a>DELEGATION 2504 2505## <a name='subsection113'></a>What is delegation? 2506 2507Delegation, simply put, is when you pass a task you've been given to one of your 2508assistants\. \(You do have assistants, don't you?\) Snit objects can do the same 2509thing\. The following example shows one way in which the __dog__ object can 2510delegate its __wag__ method and its __\-taillength__ option to its 2511__tail__ component\. 2512 2513 snit::type dog { 2514 variable mytail 2515 2516 option -taillength -configuremethod SetTailOption -cgetmethod GetTailOption 2517 2518 method SetTailOption {option value} { 2519 $mytail configure $option $value 2520 } 2521 2522 method GetTailOption {option} { 2523 $mytail cget $option 2524 } 2525 2526 method wag {} { 2527 $mytail wag 2528 } 2529 2530 constructor {args} { 2531 install mytail using tail %AUTO% -partof $self 2532 $self configurelist $args 2533 } 2534 2535 } 2536 2537This is the hard way to do it, by it demonstrates what delegation is all about\. 2538See the following answers for the easy way to do it\. 2539 2540Note that the constructor calls the __configurelist__ method 2541__[after](\.\./\.\./\.\./\.\./index\.md\#after)__ it creates its __tail__; 2542otherwise, if __\-taillength__ appeared in the list of __args__ we'd get 2543an error\. 2544 2545## <a name='subsection114'></a>How can I delegate a method to a component object? 2546 2547Delegation occurs frequently enough that Snit makes it easy\. Any method can be 2548delegated to any component or type component by placing a single 2549__delegate__ statement in the type definition\. \(See 2550[COMPONENTS](#section14) and [TYPE COMPONENTS](#section15) for more 2551information about component names\.\) 2552 2553For example, here's a much better way to delegate the __dog__ object's 2554__wag__ method: 2555 2556 % snit::type dog { 2557 delegate method wag to mytail 2558 2559 constructor {} { 2560 install mytail using tail %AUTO% 2561 } 2562 } 2563 ::dog 2564 % snit::type tail { 2565 method wag {} { return "Wag, wag, wag."} 2566 } 2567 ::tail 2568 % dog spot 2569 ::spot 2570 % spot wag 2571 Wag, wag, wag. 2572 2573This code has the same effect as the code shown under the previous question: 2574when a __dog__'s __wag__ method is called, the call and its arguments 2575are passed along automatically to the __tail__ object\. 2576 2577Note that when a component is mentioned in a __delegate__ statement, the 2578component's instance variable is defined implicitly\. However, it's still good 2579practice to declare it explicitly using the __component__ statement\. 2580 2581Note also that you can define a method name using the 2582__[method](\.\./\.\./\.\./\.\./index\.md\#method)__ statement, or you can define 2583it using __delegate__; you can't do both\. 2584 2585## <a name='subsection115'></a>Can I delegate to a method with a different name? 2586 2587Suppose you wanted to delegate the __dog__'s __wagtail__ method to the 2588__tail__'s __wag__ method\. After all you wag the tail, not the dog\. It's 2589easily done: 2590 2591 snit::type dog { 2592 delegate method wagtail to mytail as wag 2593 2594 constructor {args} { 2595 install mytail using tail %AUTO% -partof $self 2596 $self configurelist $args 2597 } 2598 } 2599 2600## <a name='subsection116'></a>Can I delegate to a method with additional arguments? 2601 2602Suppose the __tail__'s __wag__ method takes as an argument the number of 2603times the tail should be wagged\. You want to delegate the __dog__'s 2604__wagtail__ method to the __tail__'s __wag__ method, specifying that 2605the tail should be wagged exactly three times\. This is easily done, too: 2606 2607 snit::type dog { 2608 delegate method wagtail to mytail as {wag 3} 2609 # ... 2610 } 2611 2612 snit::type tail { 2613 method wag {count} { 2614 return [string repeat "Wag " $count] 2615 } 2616 # ... 2617 } 2618 2619## <a name='subsection117'></a>Can I delegate a method to something other than an object? 2620 2621Normal method delegation assumes that you're delegating a method \(a subcommand 2622of an object command\) to a method of another object \(a subcommand of a different 2623object command\)\. But not all Tcl objects follow Tk conventions, and not 2624everything you'd to which you'd like to delegate a method is necessary an 2625object\. Consequently, Snit makes it easy to delegate a method to pretty much 2626anything you like using the __delegate__ statement's __using__ clause\. 2627 2628Suppose your dog simulation stores dogs in a database, each dog as a single 2629record\. The database API you're using provides a number of commands to manage 2630records; each takes the record ID \(a string you choose\) as its first argument\. 2631For example, __saverec__ saves a record\. If you let the record ID be the 2632name of the dog object, you can delegate the dog's __save__ method to the 2633__saverec__ command as follows: 2634 2635 snit::type dog { 2636 delegate method save using {saverec %s} 2637 } 2638 2639The __%s__ is replaced with the instance name when the __save__ method 2640is called; any additional arguments are the appended to the resulting command\. 2641 2642The __using__ clause understands a number of other %\-conversions; in 2643addition to the instance name, you can substitute in the method name 2644\(__%m__\), the type name \(__%t__\), the instance namespace \(__%n__\), 2645the Tk window name \(__%w__\), and, if a component or typecomponent name was 2646given in the __delegate__ statement, the component's object command 2647\(__%c__\)\. 2648 2649## <a name='subsection118'></a>How can I delegate a method to a type component object? 2650 2651Just exactly as you would to a component object\. The __delegate method__ 2652statement accepts both component and type component names in its __to__ 2653clause\. 2654 2655## <a name='subsection119'></a>How can I delegate a type method to a type component object? 2656 2657Use the __delegate typemethod__ statement\. It works like __delegate 2658method__, with these differences: first, it defines a type method instead of 2659an instance method; second, the __using__ clause ignores the __%s__, 2660__%n__, and __%w__ %\-conversions\. 2661 2662Naturally, you can't delegate a type method to an instance component\.\.\.Snit 2663wouldn't know which instance should receive it\. 2664 2665## <a name='subsection120'></a>How can I delegate an option to a component object? 2666 2667The first question in this section \(see [DELEGATION](#section16)\) shows one 2668way to delegate an option to a component; but this pattern occurs often enough 2669that Snit makes it easy\. For example, every __tail__ object has a 2670__\-length__ option; we want to allow the creator of a __dog__ object to 2671set the tail's length\. We can do this: 2672 2673 % snit::type dog { 2674 delegate option -length to mytail 2675 2676 constructor {args} { 2677 install mytail using tail %AUTO% -partof $self 2678 $self configurelist $args 2679 } 2680 } 2681 ::dog 2682 % snit::type tail { 2683 option -partof 2684 option -length 5 2685 } 2686 ::tail 2687 % dog spot -length 7 2688 ::spot 2689 % spot cget -length 2690 7 2691 2692This produces nearly the same result as the __\-configuremethod__ and 2693__\-cgetmethod__ shown under the first question in this section: whenever a 2694__dog__ object's __\-length__ option is set or retrieved, the underlying 2695__tail__ object's option is set or retrieved in turn\. 2696 2697Note that you can define an option name using the __option__ statement, or 2698you can define it using __delegate__; you can't do both\. 2699 2700## <a name='subsection121'></a>Can I delegate to an option with a different name? 2701 2702In the previous answer we delegated the __dog__'s __\-length__ option 2703down to its __tail__\. This is, of course, wrong\. The dog has a length, and 2704the tail has a length, and they are different\. What we'd really like to do is 2705give the __dog__ a __\-taillength__ option, but delegate it to the 2706__tail__'s __\-length__ option: 2707 2708 snit::type dog { 2709 delegate option -taillength to mytail as -length 2710 2711 constructor {args} { 2712 set mytail [tail %AUTO% -partof $self] 2713 $self configurelist $args 2714 } 2715 } 2716 2717## <a name='subsection122'></a>How can I delegate any unrecognized method or option to a component object? 2718 2719It may happen that a Snit object gets most of its behavior from one of its 2720components\. This often happens with __snit::widgetadaptors__, for example, 2721where we wish to slightly the modify the behavior of an existing widget\. To 2722carry on with our __dog__ example, however, suppose that we have a 2723__snit::type__ called __animal__ that implements a variety of animal 2724behaviors\-\-moving, eating, sleeping, and so forth\. We want our __dog__ 2725objects to inherit these same behaviors, while adding dog\-like behaviors of its 2726own\. Here's how we can give a __dog__ methods and options of its own while 2727delegating all other methods and options to its __animal__ component: 2728 2729 snit::type dog { 2730 delegate option * to animal 2731 delegate method * to animal 2732 2733 option -akc 0 2734 2735 constructor {args} { 2736 install animal using animal %AUTO% -name $self 2737 $self configurelist $args 2738 } 2739 2740 method wag {} { 2741 return "$self wags its tail" 2742 } 2743 } 2744 2745That's it\. A __dog__ is now an __animal__ that has a __\-akc__ option 2746and can __wag__ its tail\. 2747 2748Note that we don't need to specify the full list of method names or option names 2749that __animal__ will receive\. It gets anything __dog__ doesn't 2750recognize\-\-and if it doesn't recognize it either, it will simply throw an error, 2751just as it should\. 2752 2753You can also delegate all unknown type methods to a type component using 2754__delegate typemethod \*__\. 2755 2756## <a name='subsection123'></a>How can I delegate all but certain methods or options to a component? 2757 2758In the previous answer, we said that every __dog__ is an __animal__ by 2759delegating all unknown methods and options to the __animal__ component\. But 2760what if the __animal__ type has some methods or options that we'd like to 2761suppress? 2762 2763One solution is to explicitly delegate all the options and methods, and forgo 2764the convenience of __delegate method \*__ and __delegate option \*__\. But 2765if we wish to suppress only a few options or methods, there's an easier way: 2766 2767 snit::type dog { 2768 delegate option * to animal except -numlegs 2769 delegate method * to animal except {fly climb} 2770 2771 # ... 2772 2773 constructor {args} { 2774 install animal using animal %AUTO% -name $self -numlegs 4 2775 $self configurelist $args 2776 } 2777 2778 # ... 2779 } 2780 2781Dogs have four legs, so we specify that explicitly when we create the 2782__animal__ component, and explicitly exclude __\-numlegs__ from the set 2783of delegated options\. Similarly, dogs can neither __fly__ nor __climb__, 2784so we exclude those __animal__ methods as shown\. 2785 2786## <a name='subsection124'></a>Can a hierarchical method be delegated? 2787 2788Yes; just specify multiple words in the delegated method's name: 2789 2790 snit::type tail { 2791 method wag {} {return "Wag, wag"} 2792 method droop {} {return "Droop, droop"} 2793 } 2794 2795 snit::type dog { 2796 delegate method {tail wag} to mytail 2797 delegate method {tail droop} to mytail 2798 2799 # ... 2800 2801 constructor {args} { 2802 install mytail using tail %AUTO% 2803 $self configurelist $args 2804 } 2805 2806 # ... 2807 } 2808 2809Unrecognized hierarchical methods can also be delegated; the following code 2810delegates all subcommands of the "tail" method to the "mytail" component: 2811 2812 snit::type dog { 2813 delegate method {tail *} to mytail 2814 2815 # ... 2816 } 2817 2818# <a name='section17'></a>WIDGETS 2819 2820## <a name='subsection125'></a>What is a snit::widget? 2821 2822A __snit::widget__ is the Snit version of what Tcl programmers usually call 2823a *megawidget*: a widget\-like object usually consisting of one or more Tk 2824widgets all contained within a Tk frame\. 2825 2826A __snit::widget__ is also a special kind of __snit::type__\. Just about 2827everything in this FAQ list that relates to __snit::types__ also applies to 2828__snit::widgets__\. 2829 2830## <a name='subsection126'></a>How do I define a snit::widget? 2831 2832__snit::widgets__ are defined using the __snit::widget__ command, just 2833as __snit::types__ are defined by the __snit::type__ command\. 2834 2835The body of the definition can contain all of the same kinds of statements, plus 2836a couple of others which will be mentioned below\. 2837 2838## <a name='subsection127'></a>How do snit::widgets differ from snit::types? 2839 2840 - The name of an instance of a __snit::type__ can be any valid Tcl command 2841 name, in any namespace\. The name of an instance of a __snit::widget__ 2842 must be a valid Tk widget name, and its parent widget must already exist\. 2843 2844 - An instance of a __snit::type__ can be destroyed by calling its 2845 __destroy__ method\. Instances of a __snit::widget__ have no destroy 2846 method; use the Tk __destroy__ command instead\. 2847 2848 - Every instance of a __snit::widget__ has one predefined component called 2849 its __hull__ component\. The hull is usually a Tk 2850 __[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ or __toplevel__ widget; 2851 any other widgets created as part of the __snit::widget__ will usually 2852 be contained within the hull\. 2853 2854 - __snit::widget__s can have their options receive default values from 2855 [THE TK OPTION DATABASE](#section19)\. 2856 2857## <a name='subsection128'></a>What is a hull component? 2858 2859Snit can't create a Tk widget object; only Tk can do that\. Thus, every instance 2860of a __snit::widget__ must be wrapped around a genuine Tk widget; this Tk 2861widget is called the *hull component*\. Snit effectively piggybacks the 2862behavior you define \(methods, options, and so forth\) on top of the hull 2863component so that the whole thing behaves like a standard Tk widget\. 2864 2865For __snit::widget__s the hull component must be a Tk widget that defines 2866the __\-class__ option\. 2867 2868__snit::widgetadaptor__s differ from __snit::widget__s chiefly in that 2869any kind of widget can be used as the hull component; see [WIDGET 2870ADAPTORS](#section18)\. 2871 2872## <a name='subsection129'></a>How can I set the hull type for a snit::widget? 2873 2874A __snit::widget__'s hull component will usually be a Tk 2875__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ widget; however, it may be any 2876Tk widget that defines the __\-class__ option\. You can explicitly choose the 2877hull type you prefer by including the __hulltype__ command in the widget 2878definition: 2879 2880 snit::widget mytoplevel { 2881 hulltype toplevel 2882 2883 # ... 2884 } 2885 2886If no __hulltype__ command appears, the hull will be a 2887__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__\. 2888 2889By default, Snit recognizes the following hull types: the Tk widgets 2890__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__, __labelframe__, 2891__toplevel__, and the Tile widgets __ttk::frame__, 2892__ttk::labelframe__, and __ttk::toplevel__\. To enable the use of some 2893other kind of widget as the hull type, you can __lappend__ the widget 2894command to the variable __snit::hulltypes__ \(always provided the widget 2895defines the __\-class__ option\. For example, suppose Tk gets a new widget 2896type called a __prettyframe__: 2897 2898 lappend snit::hulltypes prettyframe 2899 2900 snit::widget mywidget { 2901 hulltype prettyframe 2902 2903 # ... 2904 } 2905 2906## <a name='subsection130'></a>How should I name widgets which are components of a snit::widget? 2907 2908Every widget, whether a genuine Tk widget or a Snit megawidget, has to have a 2909valid Tk window name\. When a __snit::widget__ is first created, its instance 2910name, __self__, is a Tk window name; however, if the __snit::widget__ is 2911used as the hull component by a __snit::widgetadaptor__ its instance name 2912will be changed to something else\. For this reason, every __snit::widget__ 2913method, constructor, destructor, and so forth is passed another implicit 2914argument, __win__, which is the window name of the megawidget\. Any children 2915should be named using __win__ as the root\. 2916 2917Thus, suppose you're writing a toolbar widget, a frame consisting of a number of 2918buttons placed side\-by\-side\. It might look something like this: 2919 2920 snit::widget toolbar { 2921 delegate option * to hull 2922 2923 constructor {args} { 2924 button $win.open -text Open -command [mymethod open] 2925 button $win.save -text Save -command [mymethod save] 2926 2927 # .... 2928 2929 $self configurelist $args 2930 2931 } 2932 } 2933 2934See also the question on renaming objects, toward the top of this file\. 2935 2936# <a name='section18'></a>WIDGET ADAPTORS 2937 2938## <a name='subsection131'></a>What is a snit::widgetadaptor? 2939 2940A __snit::widgetadaptor__ is a kind of __snit::widget__\. Whereas a 2941__snit::widget__'s hull is automatically created and is always a Tk frame, a 2942__snit::widgetadaptor__ can be based on any Tk widget\-\-or on any Snit 2943megawidget, or even \(with luck\) on megawidgets defined using some other package\. 2944 2945It's called a *widget adaptor* because it allows you to take an existing 2946widget and customize its behavior\. 2947 2948## <a name='subsection132'></a>How do I define a snit::widgetadaptor? 2949 2950Use the __snit::widgetadaptor__ command\. The definition for a 2951__snit::widgetadaptor__ looks just like that for a __snit::type__ or 2952__snit::widget__, except that the constructor must create and install the 2953hull component\. 2954 2955For example, the following code creates a read\-only text widget by the simple 2956device of turning its __insert__ and __delete__ methods into no\-ops\. 2957Then, we define new methods, __ins__ and __del__, which get delegated to 2958the hull component as __insert__ and __delete__\. Thus, we've adapted the 2959text widget and given it new behavior while still leaving it fundamentally a 2960text widget\. 2961 2962 ::snit::widgetadaptor rotext { 2963 2964 constructor {args} { 2965 # Create the text widget; turn off its insert cursor 2966 installhull using text -insertwidth 0 2967 2968 # Apply any options passed at creation time. 2969 $self configurelist $args 2970 } 2971 2972 # Disable the text widget's insert and delete methods, to 2973 # make this readonly. 2974 method insert {args} {} 2975 method delete {args} {} 2976 2977 # Enable ins and del as synonyms, so the program can insert and 2978 # delete. 2979 delegate method ins to hull as insert 2980 delegate method del to hull as delete 2981 2982 # Pass all other methods and options to the real text widget, so 2983 # that the remaining behavior is as expected. 2984 delegate method * to hull 2985 delegate option * to hull 2986 } 2987 2988The most important part is in the constructor\. Whereas __snit::widget__ 2989creates the hull for you, __snit::widgetadaptor__ cannot \-\- it doesn't know 2990what kind of widget you want\. So the first thing the constructor does is create 2991the hull component \(a Tk text widget in this case\), and then installs it using 2992the __installhull__ command\. 2993 2994*Note:* There is no instance command until you create one by installing a hull 2995component\. Any attempt to pass methods to __$self__ prior to calling 2996__installhull__ will fail\. 2997 2998## <a name='subsection133'></a>Can I adapt a widget created elsewhere in the program? 2999 3000Yes\. 3001 3002At times, it can be convenient to adapt a pre\-existing widget instead of 3003creating your own\. For example, the Bwidget __PagesManager__ widget manages 3004a set of __[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ widgets, only one of 3005which is visible at a time\. The application chooses which 3006__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ is visible\. All of the These 3007__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__s are created by the 3008__PagesManager__ itself, using its __add__ method\. It's convenient to 3009adapt these frames to do what we'd like them to do\. 3010 3011In a case like this, the Tk widget will already exist when the 3012__snit::widgetadaptor__ is created\. Snit provides an alternate form of the 3013__installhull__ command for this purpose: 3014 3015 snit::widgetadaptor pageadaptor { 3016 constructor {args} { 3017 # The widget already exists; just install it. 3018 installhull $win 3019 3020 # ... 3021 } 3022 } 3023 3024## <a name='subsection134'></a>Can I adapt another megawidget? 3025 3026Maybe\. If the other megawidget is a __snit::widget__ or 3027__snit::widgetadaptor__, then yes\. If it isn't then, again, maybe\. You'll 3028have to try it and see\. You're most likely to have trouble with widget 3029destruction\-\-you have to make sure that your megawidget code receives the 3030__<Destroy>__ event before the megawidget you're adapting does\. 3031 3032# <a name='section19'></a>THE TK OPTION DATABASE 3033 3034## <a name='subsection135'></a>What is the Tk option database? 3035 3036The Tk option database is a database of default option values maintained by Tk 3037itself; every Tk application has one\. The concept of the option database derives 3038from something called the X Windows resource database; however, the option 3039database is available in every Tk implementation, including those which do not 3040use the X Windows system \(e\.g\., Microsoft Windows\)\. 3041 3042Full details about the Tk option database are beyond the scope of this document; 3043both *Practical Programming in Tcl and Tk* by Welch, Jones, and Hobbs, and 3044*Effective Tcl/Tk Programming* by Harrison and McClennan\., have good 3045introductions to it\. 3046 3047Snit is implemented so that most of the time it will simply do the right thing 3048with respect to the option database, provided that the widget developer does the 3049right thing by Snit\. The body of this section goes into great deal about what 3050Snit requires\. The following is a brief statement of the requirements, for 3051reference\. 3052 3053 - If the widget's default widget class is not what is desired, set it 3054 explicitly using the __widgetclass__ statement in the widget definition\. 3055 3056 - When defining or delegating options, specify the resource and class names 3057 explicitly when necessary\. 3058 3059 - Use the __installhull using__ command to create and install the hull for 3060 __snit::widgetadaptor__s\. 3061 3062 - Use the __install__ command to create and install all components which 3063 are widgets\. 3064 3065 - Use the __install__ command to create and install components which 3066 aren't widgets if you'd like them to receive option values from the option 3067 database\. 3068 3069The interaction of Tk widgets with the option database is a complex thing; the 3070interaction of Snit with the option database is even more so, and repays 3071attention to detail\. 3072 3073## <a name='subsection136'></a>Do snit::types use the Tk option database? 3074 3075No, they don't; querying the option database requires a Tk window name, and 3076__snit::type__s don't have one\. 3077 3078If you create an instance of a __snit::type__ as a component of a 3079__snit::widget__ or __snit::widgetadaptor__, on the other hand, and if 3080any options are delegated to the component, and if you use __install__ to 3081create and install it, then the megawidget will query the option database on the 3082__snit::type__'s behalf\. This might or might not be what you want, so take 3083care\. 3084 3085## <a name='subsection137'></a>What is my snit::widget's widget class? 3086 3087Every Tk widget has a "widget class": a name that is used when adding option 3088settings to the database\. For Tk widgets, the widget class is the same as the 3089widget command name with an initial capital\. For example, the widget class of 3090the Tk __button__ widget is __Button__\. 3091 3092Similarly, the widget class of a __snit::widget__ defaults to the 3093unqualified type name with the first letter capitalized\. For example, the widget 3094class of 3095 3096 snit::widget ::mylibrary::scrolledText { ... } 3097 3098is __ScrolledText__\. 3099 3100The widget class can also be set explicitly using the __widgetclass__ 3101statement within the __snit::widget__ definition: 3102 3103 snit::widget ::mylibrary::scrolledText { 3104 widgetclass Text 3105 3106 # ... 3107 } 3108 3109The above definition says that a __scrolledText__ megawidget has the same 3110widget class as an ordinary __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ 3111widget\. This might or might not be a good idea, depending on how the rest of the 3112megawidget is defined, and how its options are delegated\. 3113 3114## <a name='subsection138'></a>What is my snit::widgetadaptor's widget class? 3115 3116The widget class of a __snit::widgetadaptor__ is just the widget class of 3117its hull widget; Snit has no control over this\. 3118 3119Note that the widget class can be changed only for 3120__[frame](\.\./\.\./\.\./\.\./index\.md\#frame)__ and __toplevel__ widgets, 3121which is why these are the valid hull types for __snit::widget__s\. 3122 3123Try to use __snit::widgetadaptor__s only to make small modifications to 3124another widget's behavior\. Then, it will usually not make sense to change the 3125widget's widget class anyway\. 3126 3127## <a name='subsection139'></a>What are option resource and class names? 3128 3129Every Tk widget option has three names: the option name, the resource name, and 3130the class name\. The option name begins with a hyphen and is all lowercase; it's 3131used when creating widgets, and with the __configure__ and __cget__ 3132commands\. 3133 3134The resource and class names are used to initialize option default values by 3135querying the option database\. The resource name is usually just the option name 3136minus the hyphen, but may contain uppercase letters at word boundaries; the 3137class name is usually just the resource name with an initial capital, but not 3138always\. For example, here are the option, resource, and class names for several 3139Tk __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget options: 3140 3141 -background background Background 3142 -borderwidth borderWidth BorderWidth 3143 -insertborderwidth insertBorderWidth BorderWidth 3144 -padx padX Pad 3145 3146As is easily seen, sometimes the resource and class names can be inferred from 3147the option name, but not always\. 3148 3149## <a name='subsection140'></a>What are the resource and class names for my megawidget's options? 3150 3151For options implicitly delegated to a component using __delegate option \*__, 3152the resource and class names will be exactly those defined by the component\. The 3153__configure__ method returns these names, along with the option's default 3154and current values: 3155 3156 % snit::widget mytext { 3157 delegate option * to text 3158 3159 constructor {args} { 3160 install text using text .text 3161 # ... 3162 } 3163 3164 # ... 3165 } 3166 ::mytext 3167 % mytext .text 3168 .text 3169 % .text configure -padx 3170 -padx padX Pad 1 1 3171 % 3172 3173For all other options \(whether locally defined or explicitly delegated\), the 3174resource and class names can be defined explicitly, or they can be allowed to 3175have default values\. 3176 3177By default, the resource name is just the option name minus the hyphen; the the 3178class name is just the option name with an initial capital letter\. For example, 3179suppose we explicitly delegate "\-padx": 3180 3181 % snit::widget mytext { 3182 option -myvalue 5 3183 3184 delegate option -padx to text 3185 delegate option * to text 3186 3187 constructor {args} { 3188 install text using text .text 3189 # ... 3190 } 3191 3192 # ... 3193 } 3194 ::mytext 3195 % mytext .text 3196 .text 3197 % .text configure -myvalue 3198 -myvalue myvalue Myvalue 5 5 3199 % .text configure -padx 3200 -padx padx Padx 1 1 3201 % 3202 3203Here the resource and class names are chosen using the default rules\. Often 3204these rules are sufficient, but in the case of "\-padx" we'd most likely prefer 3205that the option's resource and class names are the same as for the built\-in Tk 3206widgets\. This is easily done: 3207 3208 % snit::widget mytext { 3209 delegate option {-padx padX Pad} to text 3210 3211 # ... 3212 } 3213 ::mytext 3214 % mytext .text 3215 .text 3216 % .text configure -padx 3217 -padx padX Pad 1 1 3218 % 3219 3220## <a name='subsection141'></a>How does Snit initialize my megawidget's locally\-defined options? 3221 3222The option database is queried for each of the megawidget's locally\-defined 3223options, using the option's resource and class name\. If the result isn't "", 3224then it replaces the default value given in widget definition\. In either case, 3225the default can be overridden by the caller\. For example, 3226 3227 option add *Mywidget.texture pebbled 3228 3229 snit::widget mywidget { 3230 option -texture smooth 3231 # ... 3232 } 3233 3234 mywidget .mywidget -texture greasy 3235 3236Here, __\-texture__ would normally default to "smooth", but because of the 3237entry added to the option database it defaults to "pebbled"\. However, the caller 3238has explicitly overridden the default, and so the new widget will be "greasy"\. 3239 3240## <a name='subsection142'></a>How does Snit initialize delegated options? 3241 3242That depends on whether the options are delegated to the hull, or to some other 3243component\. 3244 3245## <a name='subsection143'></a>How does Snit initialize options delegated to the hull? 3246 3247A __snit::widget__'s hull is a widget, and given that its class has been set 3248it is expected to query the option database for itself\. The only exception 3249concerns options that are delegated to it with a different name\. Consider the 3250following code: 3251 3252 option add *Mywidget.borderWidth 5 3253 option add *Mywidget.relief sunken 3254 option add *Mywidget.hullbackground red 3255 option add *Mywidget.background green 3256 3257 snit::widget mywidget { 3258 delegate option -borderwidth to hull 3259 delegate option -hullbackground to hull as -background 3260 delegate option * to hull 3261 # ... 3262 } 3263 3264 mywidget .mywidget 3265 3266 set A [.mywidget cget -relief] 3267 set B [.mywidget cget -hullbackground] 3268 set C [.mywidget cget -background] 3269 set D [.mywidget cget -borderwidth] 3270 3271The question is, what are the values of variables A, B, C and D? 3272 3273The value of A is "sunken"\. The hull is a Tk frame which has been given the 3274widget class __Mywidget__; it will automatically query the option database 3275and pick up this value\. Since the __\-relief__ option is implicitly delegated 3276to the hull, Snit takes no action\. 3277 3278The value of B is "red"\. The hull will automatically pick up the value "green" 3279for its __\-background__ option, just as it picked up the __\-relief__ 3280value\. However, Snit knows that __\-hullbackground__ is mapped to the hull's 3281__\-background__ option; hence, it queries the option database for 3282__\-hullbackground__ and gets "red" and updates the hull accordingly\. 3283 3284The value of C is also "red", because __\-background__ is implicitly 3285delegated to the hull; thus, retrieving it is the same as retrieving 3286__\-hullbackground__\. Note that this case is unusual; the __\-background__ 3287option should probably have been excluded using the delegate statement's 3288__except__ clause, or \(more likely\) delegated to some other component\. 3289 3290The value of D is "5", but not for the reason you think\. Note that as it is 3291defined above, the resource name for __\-borderwidth__ defaults to 3292__borderwidth__, whereas the option database entry is __borderWidth__, 3293in accordance with the standard Tk naming for this option\. As with 3294__\-relief__, the hull picks up its own __\-borderwidth__ option before 3295Snit does anything\. Because the option is delegated under its own name, Snit 3296assumes that the correct thing has happened, and doesn't worry about it any 3297further\. To avoid confusion, the __\-borderwidth__ option should have been 3298delegated like this: 3299 3300 delegate option {-borderwidth borderWidth BorderWidth} to hull 3301 3302For __snit::widgetadaptor__s, the case is somewhat altered\. Widget adaptors 3303retain the widget class of their hull, and the hull is not created automatically 3304by Snit\. Instead, the __snit::widgetadaptor__ must call __installhull__ 3305in its constructor\. The normal way to do this is as follows: 3306 3307 snit::widgetadaptor mywidget { 3308 # ... 3309 constructor {args} { 3310 # ... 3311 installhull using text -foreground white 3312 # ... 3313 } 3314 # ... 3315 } 3316 3317In this case, the __installhull__ command will create the hull using a 3318command like this: 3319 3320 set hull [text $win -foreground white] 3321 3322The hull is a __[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget, so its 3323widget class is __Text__\. Just as with __snit::widget__ hulls, Snit 3324assumes that it will pick up all of its normal option values automatically, 3325without help from Snit\. Options delegated from a different name are initialized 3326from the option database in the same way as described above\. 3327 3328In earlier versions of Snit, __snit::widgetadaptor__s were expected to call 3329__installhull__ like this: 3330 3331 installhull [text $win -foreground white] 3332 3333This form still works\-\-but Snit will not query the option database as described 3334above\. 3335 3336## <a name='subsection144'></a>How does Snit initialize options delegated to other components? 3337 3338For hull components, Snit assumes that Tk will do most of the work 3339automatically\. Non\-hull components are somewhat more complicated, because they 3340are matched against the option database twice\. 3341 3342A component widget remains a widget still, and is therefore initialized from the 3343option database in the usual way\. A 3344__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget remains a 3345__[text](\.\./\.\./\.\./\.\./index\.md\#text)__ widget whether it is a component 3346of a megawidget or not, and will be created as such\. 3347 3348But then, the option database is queried for all options delegated to the 3349component, and the component is initialized accordingly\-\-provided that the 3350__install__ command is used to create it\. 3351 3352Before option database support was added to Snit, the usual way to create a 3353component was to simply create it in the constructor and assign its command name 3354to the component variable: 3355 3356 snit::widget mywidget { 3357 delegate option -background to myComp 3358 3359 constructor {args} { 3360 set myComp [text $win.text -foreground black] 3361 } 3362 } 3363 3364The drawback of this method is that Snit has no opportunity to initialize the 3365component properly\. Hence, the following approach is now used: 3366 3367 snit::widget mywidget { 3368 delegate option -background to myComp 3369 3370 constructor {args} { 3371 install myComp using text $win.text -foreground black 3372 } 3373 } 3374 3375The __install__ command does the following: 3376 3377 - Builds a list of the options explicitly included in the __install__ 3378 command\-\-in this case, __\-foreground__\. 3379 3380 - Queries the option database for all options delegated explicitly to the 3381 named component\. 3382 3383 - Creates the component using the specified command, after inserting into it a 3384 list of options and values read from the option database\. Thus, the 3385 explicitly included options \(like __\-foreground__\) will override 3386 anything read from the option database\. 3387 3388 - If the widget definition implicitly delegated options to the component using 3389 __delegate option \*__, then Snit calls the newly created component's 3390 __configure__ method to receive a list of all of the component's 3391 options\. From this Snit builds a list of options implicitly delegated to the 3392 component which were not explicitly included in the __install__ command\. 3393 For all such options, Snit queries the option database and configures the 3394 component accordingly\. 3395 3396You don't really need to know all of this; just use __install__ to install 3397your components, and Snit will try to do the right thing\. 3398 3399## <a name='subsection145'></a>What happens if I install a non\-widget as a component of widget? 3400 3401A __snit::type__ never queries the option database\. However, a 3402__snit::widget__ can have non\-widget components\. And if options are 3403delegated to those components, and if the __install__ command is used to 3404install those components, then they will be initialized from the option database 3405just as widget components are\. 3406 3407However, when used within a megawidget, __install__ assumes that the created 3408component uses a reasonably standard widget\-like creation syntax\. If it doesn't, 3409don't use __install__\. 3410 3411# <a name='section20'></a>ENSEMBLE COMMANDS 3412 3413## <a name='subsection146'></a>What is an ensemble command? 3414 3415An ensemble command is a command with subcommands\. Snit objects are all ensemble 3416commands; however, the term more usually refers to commands like the standard 3417Tcl commands __[string](\.\./\.\./\.\./\.\./index\.md\#string)__, 3418__[file](\.\./\.\./\.\./\.\./index\.md\#file)__, and __clock__\. In a sense, 3419these are singleton objects\-\-there's only one instance of them\. 3420 3421## <a name='subsection147'></a>How can I create an ensemble command using Snit? 3422 3423There are two ways\-\-as a __snit::type__, or as an instance of a 3424__snit::type__\. 3425 3426## <a name='subsection148'></a>How can I create an ensemble command using an instance of a snit::type? 3427 3428Define a type whose [INSTANCE METHODS](#section5) are the subcommands of 3429your ensemble command\. Then, create an instance of the type with the desired 3430name\. 3431 3432For example, the following code uses [DELEGATION](#section16) to create a 3433work\-alike for the standard __[string](\.\./\.\./\.\./\.\./index\.md\#string)__ 3434command: 3435 3436 snit::type ::mynamespace::mystringtype { 3437 delegate method * to stringhandler 3438 3439 constructor {} { 3440 set stringhandler string 3441 } 3442 } 3443 3444 ::mynamespace::mystringtype mystring 3445 3446We create the type in a namespace, so that the type command is hidden; then we 3447create a single instance with the desired name\-\- __mystring__, in this case\. 3448 3449This method has two drawbacks\. First, it leaves the type command floating about\. 3450More seriously, your shiny new ensemble command will have __info__ and 3451__destroy__ subcommands that you probably have no use for\. But read on\. 3452 3453## <a name='subsection149'></a>How can I create an ensemble command using a snit::type? 3454 3455Define a type whose [TYPE METHODS](#section9) are the subcommands of your 3456ensemble command\. 3457 3458For example, the following code uses [DELEGATION](#section16) to create a 3459work\-alike for the standard __[string](\.\./\.\./\.\./\.\./index\.md\#string)__ 3460command: 3461 3462 snit::type mystring { 3463 delegate typemethod * to stringhandler 3464 3465 typeconstructor { 3466 set stringhandler string 3467 } 3468 } 3469 3470Now the type command itself is your ensemble command\. 3471 3472This method has only one drawback, and though it's major, it's also 3473surmountable\. Your new ensemble command will have __create__, __info__ 3474and __destroy__ subcommands you don't want\. And worse yet, since the 3475__create__ method can be implicit, users of your command will accidentally 3476be creating instances of your __mystring__ type if they should mispell one 3477of the subcommands\. The command will succeed\-\-the first time\-\-but won't do 3478what's wanted\. This is very bad\. 3479 3480The work around is to set some [PRAGMAS](#section21), as shown here: 3481 3482 snit::type mystring { 3483 pragma -hastypeinfo no 3484 pragma -hastypedestroy no 3485 pragma -hasinstances no 3486 3487 delegate typemethod * to stringhandler 3488 3489 typeconstructor { 3490 set stringhandler string 3491 } 3492 } 3493 3494Here we've used the __pragma__ statement to tell Snit that we don't want the 3495__info__ typemethod or the __destroy__ typemethod, and that our type has 3496no instances; this eliminates the __create__ typemethod and all related 3497code\. As a result, our ensemble command will be well\-behaved, with no unexpected 3498subcommands\. 3499 3500# <a name='section21'></a>PRAGMAS 3501 3502## <a name='subsection150'></a>What is a pragma? 3503 3504A pragma is an option you can set in your type definitions that affects how the 3505type is defined and how it works once it is defined\. 3506 3507## <a name='subsection151'></a>How do I set a pragma? 3508 3509Use the __pragma__ statement\. Each pragma is an option with a value; each 3510time you use the __pragma__ statement you can set one or more of them\. 3511 3512## <a name='subsection152'></a>How can I get rid of the "info" type method? 3513 3514Set the __\-hastypeinfo__ pragma to __no__: 3515 3516 snit::type dog { 3517 pragma -hastypeinfo no 3518 # ... 3519 } 3520 3521Snit will refrain from defining the __info__ type method\. 3522 3523## <a name='subsection153'></a>How can I get rid of the "destroy" type method? 3524 3525Set the __\-hastypedestroy__ pragma to __no__: 3526 3527 snit::type dog { 3528 pragma -hastypedestroy no 3529 # ... 3530 } 3531 3532Snit will refrain from defining the __destroy__ type method\. 3533 3534## <a name='subsection154'></a>How can I get rid of the "create" type method? 3535 3536Set the __\-hasinstances__ pragma to __no__: 3537 3538 snit::type dog { 3539 pragma -hasinstances no 3540 # ... 3541 } 3542 3543Snit will refrain from defining the __create__ type method; if you call the 3544type command with an unknown method name, you'll get an error instead of a new 3545instance of the type\. 3546 3547This is useful if you wish to use a __snit::type__ to define an ensemble 3548command rather than a type with instances\. 3549 3550Pragmas __\-hastypemethods__ and __\-hasinstances__ cannot both be false 3551\(or there'd be nothing left\)\. 3552 3553## <a name='subsection155'></a>How can I get rid of type methods altogether? 3554 3555Normal Tk widget type commands don't have subcommands; all they do is create 3556widgets\-\-in Snit terms, the type command calls the __create__ type method 3557directly\. To get the same behavior from Snit, set the __\-hastypemethods__ 3558pragma to __no__: 3559 3560 snit::type dog { 3561 pragma -hastypemethods no 3562 #... 3563 } 3564 3565 # Creates ::spot 3566 dog spot 3567 3568 # Tries to create an instance called ::create 3569 dog create spot 3570 3571Pragmas __\-hastypemethods__ and __\-hasinstances__ cannot both be false 3572\(or there'd be nothing left\)\. 3573 3574## <a name='subsection156'></a>Why can't I create an object that replaces an old object with the same name? 3575 3576Up until Snit 0\.95, you could use any name for an instance of a 3577__snit::type__, even if the name was already in use by some other object or 3578command\. You could do the following, for example: 3579 3580 snit::type dog { ... } 3581 3582 dog proc 3583 3584You now have a new dog named "proc", which is probably not something that you 3585really wanted to do\. As a result, Snit now throws an error if your chosen 3586instance name names an existing command\. To restore the old behavior, set the 3587__\-canreplace__ pragma to __yes__: 3588 3589 snit::type dog { 3590 pragma -canreplace yes 3591 # ... 3592 } 3593 3594## <a name='subsection157'></a>How can I make my simple type run faster? 3595 3596In Snit 1\.x, you can set the __\-simpledispatch__ pragma to __yes__\. 3597 3598Snit 1\.x method dispatch is both flexible and fast, but the flexibility comes 3599with a price\. If your type doesn't require the flexibility, the 3600__\-simpledispatch__ pragma allows you to substitute a simpler dispatch 3601mechanism that runs quite a bit faster\. The limitations are these: 3602 3603 - Methods cannot be delegated\. 3604 3605 - __uplevel__ and __upvar__ do not work as expected: the caller's 3606 scope is two levels up rather than one\. 3607 3608 - The option\-handling methods \(__cget__, __configure__, and 3609 __configurelist__\) are very slightly slower\. 3610 3611In Snit 2\.2, the __\-simpledispatch__ macro is obsolete, and ignored; all 3612Snit 2\.2 method dispatch is faster than Snit 1\.x's __\-simpledispatch__\. 3613 3614# <a name='section22'></a>MACROS 3615 3616## <a name='subsection158'></a>What is a macro? 3617 3618A Snit macro is nothing more than a Tcl proc that's defined in the Tcl 3619interpreter used to compile Snit type definitions\. 3620 3621## <a name='subsection159'></a>What are macros good for? 3622 3623You can use Snit macros to define new type definition syntax, and to support 3624conditional compilation\. 3625 3626## <a name='subsection160'></a>How do I do conditional compilation? 3627 3628Suppose you want your type to use a fast C extension if it's available; 3629otherwise, you'll fallback to a slower Tcl implementation\. You want to define 3630one set of methods in the first case, and another set in the second case\. But 3631how can your type definition know whether the fast C extension is available or 3632not? 3633 3634It's easily done\. Outside of any type definition, define a macro that returns 1 3635if the extension is available, and 0 otherwise: 3636 3637 if {$gotFastExtension} { 3638 snit::macro fastcode {} {return 1} 3639 } else { 3640 snit::macro fastcode {} {return 0} 3641 } 3642 3643Then, use your macro in your type definition: 3644 3645 snit::type dog { 3646 3647 if {[fastcode]} { 3648 # Fast methods 3649 method bark {} {...} 3650 method wagtail {} {...} 3651 } else { 3652 # Slow methods 3653 method bark {} {...} 3654 method wagtail {} {...} 3655 } 3656 } 3657 3658## <a name='subsection161'></a>How do I define new type definition syntax? 3659 3660Use a macro\. For example, your __snit::widget__'s __\-background__ option 3661should be propagated to a number of component widgets\. You could implement that 3662like this: 3663 3664 snit::widget mywidget { 3665 option -background -default white -configuremethod PropagateBackground 3666 3667 method PropagateBackground {option value} { 3668 $comp1 configure $option $value 3669 $comp2 configure $option $value 3670 $comp3 configure $option $value 3671 } 3672 } 3673 3674For one option, this is fine; if you've got a number of options, it becomes 3675tedious and error prone\. So package it as a macro: 3676 3677 snit::macro propagate {option "to" components} { 3678 option $option -configuremethod Propagate$option 3679 3680 set body "\n" 3681 3682 foreach comp $components { 3683 append body "\$$comp configure $option \$value\n" 3684 } 3685 3686 method Propagate$option {option value} $body 3687 } 3688 3689Then you can use it like this: 3690 3691 snit::widget mywidget { 3692 option -background default -white 3693 option -foreground default -black 3694 3695 propagate -background to {comp1 comp2 comp3} 3696 propagate -foreground to {comp1 comp2 comp3} 3697 } 3698 3699## <a name='subsection162'></a>Are there are restrictions on macro names? 3700 3701Yes, there are\. You can't redefine any standard Tcl commands or Snit type 3702definition statements\. You can use any other command name, including the name of 3703a previously defined macro\. 3704 3705If you're using Snit macros in your application, go ahead and name them in the 3706global namespace, as shown above\. But if you're using them to define types or 3707widgets for use by others, you should define your macros in the same namespace 3708as your types or widgets\. That way, they won't conflict with other people's 3709macros\. 3710 3711If my fancy __snit::widget__ is called __::mylib::mywidget__, for 3712example, then I should define my __propagate__ macro as 3713__::mylib::propagate__: 3714 3715 snit::macro mylib::propagate {option "to" components} { ... } 3716 3717 snit::widget ::mylib::mywidget { 3718 option -background default -white 3719 option -foreground default -black 3720 3721 mylib::propagate -background to {comp1 comp2 comp3} 3722 mylib::propagate -foreground to {comp1 comp2 comp3} 3723 } 3724 3725# <a name='section23'></a>Bugs, Ideas, Feedback 3726 3727This document, and the package it describes, will undoubtedly contain bugs and 3728other problems\. Please report such in the category *snit* of the [Tcllib 3729Trackers](http://core\.tcl\.tk/tcllib/reportlist)\. Please also report any ideas 3730for enhancements you may have for either package and/or documentation\. 3731 3732When proposing code changes, please provide *unified diffs*, i\.e the output of 3733__diff \-u__\. 3734 3735Note further that *attachments* are strongly preferred over inlined patches\. 3736Attachments can be made by going to the __Edit__ form of the ticket 3737immediately after its creation, and then using the left\-most button in the 3738secondary navigation bar\. 3739 3740# <a name='keywords'></a>KEYWORDS 3741 3742[BWidget](\.\./\.\./\.\./\.\./index\.md\#bwidget), [C\+\+](\.\./\.\./\.\./\.\./index\.md\#c\_), 3743[Incr Tcl](\.\./\.\./\.\./\.\./index\.md\#incr\_tcl), 3744[adaptors](\.\./\.\./\.\./\.\./index\.md\#adaptors), 3745[class](\.\./\.\./\.\./\.\./index\.md\#class), [mega 3746widget](\.\./\.\./\.\./\.\./index\.md\#mega\_widget), 3747[object](\.\./\.\./\.\./\.\./index\.md\#object), [object 3748oriented](\.\./\.\./\.\./\.\./index\.md\#object\_oriented), 3749[widget](\.\./\.\./\.\./\.\./index\.md\#widget), [widget 3750adaptors](\.\./\.\./\.\./\.\./index\.md\#widget\_adaptors) 3751 3752# <a name='category'></a>CATEGORY 3753 3754Programming tools 3755 3756# <a name='copyright'></a>COPYRIGHT 3757 3758Copyright © 2003\-2006, by William H\. Duquette 3759