On Tuesday 14 August 2001 09:38 am, Dave Thomas wrote: > Perhaps if we could see an actual example of where this is needed we > could discuss this better. I know there was some talk a while back of > some code that handled (I think) archives or somesuch. Could be see > the code for this so we could think about it. My discussion of archives was in a different context: that of changing classes of objects. I see lots of problems with doing this in Ruby, which is why I have been pushing for become(), which would be a cleaner way to do this in Ruby (or in Smalltalk). If you want to see my code that changes classes, it's on CPAN, in Perl, at http://www.cpan.org/modules/by-authors/id/N/NE/NEDKONZ/Archive-Zip-0.11.tar.gz But this is a big module, and you shouldn't have to read it to understand the situation. Here's the classes that make up the relevant part of the object model: Archive::Zip Common base class, has defs. Archive::Zip::Archive A Zip archive. Archive::Zip::Member Abstract superclass for all members. Archive::Zip::StringMember Member made from a string Archive::Zip::FileMember Member made from an external file Archive::Zip::ZipFileMember Member that lives in a zip file Archive::Zip::NewFileMember Member whose data is in a file Archive::Zip::DirectoryMember Member that is a directory There are a couple of places where object class changes occur. One trivial one (in readFromFileHandle()) is from Archive::Zip::ZipFileMember to Archive::Zip::DirectoryMember, after the member header is read from the zip file. The headers for both ZipFileMember and DirectoryMember are identical, except for a single bit that says that the member is in fact a directory. Since the incoming zip file that is being read from is not necessarily seekable, an alternative might be to read the header data, look inside it, and then call one of two constructors. Either would be easy; since it's trivial to change classes of an object in Perl, I did it this way. The more interesting one is in Archive::Zip::Member::contents(). If you're reading the contents of a member, the member has its own method of getting to the data (which may be compressed in a zip file, uncompressed in another file, in a string, etc.). But if you are setting the contents of a member to a string, the effective type of the member has to change to Archive::Zip::StringMember (which keeps its data in a string). The problem with this is that there are existing references to the old member (like, for instance, the one through which contents() was called). If I just substituted a new Archive::Zip::StringMember for the old member in the archive, these references would refer to invalid members, rather than the new StringMember. Again, because of the ease of changing classes in Perl (and the lack of become()), I chose to change classes in this case. In Ruby, it would make more sense to use become() to do this, if we had it. I realize that this could be done through delegation to a data-holding object that could privately be changed. It's just that the added complexity and inefficiency of this solution is more a reaction to language limitations (no become()) than a superior design choice. It's interesting to read the GOF Design Patterns book and to ask yourself how many of the patterns given are a reaction to the limitations of C++. Some of the patterns would, in fact, be trivial in other languages. For instance, the Decorator pattern could be done instead with Ruby's singleton classes. The State pattern in Self could consist of merely changing one parent slot, and in Perl could consist of a single bless() call to change the class. -- Ned Konz currently: Stanwood, WA email: ned / bike-nomad.com homepage: http://bike-nomad.com