I come from a different school of languages so I would perhaps do something 
like the following:

warehouse.nim: 
    
    
    type
        # We want everything on the shelf to be a Box
        Box* = ref object of RootObj
        Warehouse* = ref object
          shelf: seq[Box] # We do not use * to export the shelf
    
    # IMHO these procs should be in this module, not the other way around,
    # encapsulation is better.
    proc pushbox*[T: Box](w: Warehouse, b: T) =
        w.shelf.add(b)
    
    # Fiddling with [T] here didn't fly which I suspect has to do with
    # the simple fact that we don't know what is coming out from the
    # seq until at runtime.
    proc popbox*(w: Warehouse): Box =
        w.shelf.pop
    
    # Nim style constructor proc
    proc newWarehouse*(): Warehouse =
      Warehouse(shelf: newSeq[Box]())
    
    

box.nim: 
    
    
    import warehouse
    
    type
        BoxOfEggs = ref object of Box
          number: int
        BoxOfBananas = ref object of Box
          color: string
        Banana = ref object of RootObj
    
    var eggs = BoxOfEggs()
    var bananas = BoxOfBananas()
    var banana = Banana()
    var warehouse = newWarehouse()
    
    warehouse.pushbox(eggs)
    warehouse.pushbox(bananas)
    # Below line will not compile:
    #  Error: type mismatch: got (Warehouse, Banana)
    #   but expected one of:
    #     proc pushbox[T: Box](w: Warehouse; b: T)
    #
    #warehouse.pushbox(banana)
    
    # Here we get a Box out of popbox, but the runtime Conversion is type safe
    # so will cause a runtime ObjectConversionError if it's an BoxOfEggs or 
vice versa
    var myBananas: BoxOfBananas
    myBananas = BoxOfBananas(warehouse.popbox())
    
    var myEggs: BoxOfEggs
    myEggs = warehouse.popbox().BoxOfEggs # Different syntax style
    
    # Below line will not compile:
    #   type mismatch: got (Box) but expected 'Banana = ref Banana:ObjectType'
    #var myBanana: Banana = Banana(warehouse.popbox())
    

Reply via email to