I don't know where I got the assumption that there was a problem, in retrospect. The concern I had was that the BaseFilesystemItemCache and IFilesystemItem classes (respectively, a nominal abstract class and a nominal interface) both needed to know about each other in order for a filesystem item to be deleted both as the object-instance representing the actual item, and within the item-cache that is being provided. That would require that each IFilesystemItem-derived instance needing to know what a BaseFilesystemItemCache is (in order to pass one to the constructor and be able to type-check it at construction), and be able to pass a "remove" call on to it's cache. At the same time, any BaseFilesystemItemCache instance would need to know what an IFilesystemItem is, in order to type-check that items being added conform to interface expectations.
Simplified, the relevant functionality would look something like this:
class BaseFilesystemItemCache( object ): def __init__( self ): if self.__class__ == BaseFilesystemItemCache: raise NotImplementedError( 'BaseFilesystemItemCache is nominally an abstract class, and should not be instantiated.' ) self.Cache = [] def Add( self, item ): if not isinstance( item, IFilesystemItem ): raise TypeError( '%s.Add error: Expected an instance implementing IFilesystemItem.' % ( self.__class__.__name__ ) ) self.Cache.append( item ) item.Cache = self def Remove( self, item ): if item in self.Cache: self.Cache.remove( item ) class IFilesystemItem( object ): def __init__( self, cache=None ): self.Cache = None if self.__class__ == IFilesystemItem: raise NotImplementedError( 'IFilesystemItem is nominally an interface, and should not be instantiated.' ) if cache != None and not isinstance( cache, BaseFilesystemItemCache ): raise TypeError( '%s error: Expected a BaseFilesystemItemCache instance for cache' % ( self.__class__.__name__ ) ) if cache: self.Cache = cache def __del__( self ): if self.Cache: self.Cache.Remove( self ) class TestCache( BaseFilesystemItemCache ): def __init__( self ): BaseFilesystemItemCache.__init__( self ) class TestItem( IFilesystemItem ): def __init__( self, cache=None ): IFilesystemItem.__init__( self, cache )
Given what I thought I knew, my expectation was that an error would be raised somewhere along the line, just because of the interpretation/compilation sequence that I thought Python used.
But this code runs (it doesn't do anything, but it raises no errors, either).
I added a few more lines to create a TestCache and a couple of TestItems:
cache = TestCache() item1 = TestItem() item2 = TestItem() # At this point, nothing's been added to the cache: print "Empty Cache" print cache.Cache print print "Caching item2", item2 cache.Add( item2 ) print cache.Cache print print "Caching item1", item1 cache.Add( item1 ) print cache.Cache print print "Removing item2" cache.Remove( item2 ) print cache.Cache
and it shows that the cache add/remove cycle works as I'd originally wanted:
Empty Cache [] Caching item2 __main__.TestItem object at 0xb769f2ac [__main__.TestItem object at 0xb769f2ac] Caching item1 __main__.TestItem object at 0xb769f28c [__main__.TestItem object at 0xb769f2ac, __main__.TestItem object at 0xb769f28c] Removing item2 [__main__.TestItem object at 0xb769f28c]
In retrospect, I think that I was thinking of object inheritance restrictions - a class cannot derive from another class that isn't earlier in the same file or external - though I'm really not certain how I came to the assumption I did.
So: Check your assumptions... Lesson learned...
No comments:
Post a Comment