From: Mathieu Bouchard Date: 2001-05-30T10:28:09+09:00 Subject: [ruby-talk:15997] Re: If you want explicit instvar definitions... On Mon, 28 May 2001, Stefan Matthias Aust wrote: > To allow a better documentation of classes, I added a "var" method to > the kernel module which helps me to write down instance variable > definition is a readable manner. I'd like to some opinions whether > this is a stupid idea or a useful one. In dynamically-typed language circles there is the consensus that type-checking is what the language already does and that you should not seek to put any explicit type-checking. Now, there's of course a difference between this wish, and my opinion (which I also call "Reality"). My opinion is that: in several cases you *need* type declarations; in many other cases, you wish they were there; and a dynamic language gifts you with the possibility to invent your own kinds of types, type-declarations, and type-checking. For example, the X11 client protocol codec I'm writing right now (RubyX11) uses its own type declarations as a protocol specification. It also uses it for ordinary type-checking because that traps a large amount of bugs. But for many other domains, types aren't so useful beyond what the language offer, that is true. > class Game > var :name, 'String' > var :turn, 'Integer' > var :players, 'Array', :readonly > var :worlds, 'Array', :readonly > end why not: var :name, String var :turn, Integer var :players, Array.of(Player), :read var :worlds, Array.of(World), :read If you wish to do checking of generic types, then you have several options: you can make the accessor check all the contents of the array, or you can have the array checking contents that are introduced in it. (Blatant plug: this is yet another 10-line program using MetaRuby). In both cases, you'll have to implement Array.of(). > This currently only works for non-generic types, but with more effort > (and meta-magic) it should be possible to also support Array and > Hash style type checks. My idea is to wrapp arrays and hashes > when they are assigned to the instance variable using some proxy > object which then intercepts the []= method and delegates all other > methods to the original. you could also simply do: module TypedArray def []=(*args) raise TypeError if ... super end end a = [] a.extend TypedArray But then, you have also to wrap a few other methods that bypass your implementation of #[]= because they call each other directly at the C level (or they access the array directly). Those are #map!, #collect!, #concat, #fill, #flatten!, #push, #<<, #unshift, and I think it's all. You can't pass arguments when you call Object#extend, but you could have a write-once field called :element_type, which you would use to set the type. matju