Multiple object types on a list?

SLotman

Active member
3rd Party Module Dev
Joined
Jul 3, 2017
Messages
191
That is basically my question. Let me explain what I want to do...

I want to create a "virtual bag" where I can drop all sorts of things: weapons, potions, armor, scrolls... whatever. Then I just do a "grab" and take a random item from it.

Is there a way a "List" can hold multiple classes instead of a single one?
So far, this is what I have, but I don't think it will work.


Code:
Class Bag<T>
    Field list:List<T>
 
    Method New()
        list = New List<T>
    End Method
 
    Method add(value:T)
        list.AddLast(value)
    End Method
 
    Method remove(value:T)
        list.removeFirst(value)
    End Method
 
    Method clear()
        list.Clear()
    End Method
 
    Method get:T()
        Local c:Int = list.Count()-1
        If c<=0 Then Return Null
    
        Local item:T
        Local r:Int = Rand(0, c)
        Local i:Int = 0
    
        For item = Eachin list
            If i = r Then Return item
            i+=1
        Next
    
        Return Null ' error?
    End Method
End Class

But I don't think this will work. I know, I can always make all classes 'extend' from a single one and use *that* in the list. But I want an "all purpose" solution, that I could drop on any project and use it, without this 'caveat'.

Is there a way to do this in Cerberus? Maybe if I replace T with "Object", would it work?
 
Last edited:

SLotman

Active member
3rd Party Module Dev
Joined
Jul 3, 2017
Messages
191
Yup, using "Object" works :)
(I can't add primitives like Int, String, etc - but that's fine!)
 

MikeHart

Administrator
Joined
Jun 19, 2017
Messages
3,281
With type casting, it works:

Cerberus:
Strict

'*******************************************************
Class temp
    Field type:Int = 0
End

'*******************************************************
Class one Extends temp

    Field name:String

    Method New()
        type=1
    End

    Method Output:Void()
        Print "name="+name
    End
    Method out1:Void()
        Print "This is class one"
    End
End

'*******************************************************
Class two Extends temp
    Field value:Int=-1
    
    Method New()
        type=2
    End
    Method Output:Void()
        Print "value="+value
    End
    
    Method xxx:Void()
        Print "This is a dummy call"
    End
    Method out2:Void()
        Print "This is class two"
        xxx()
    End
End


'*******************************************************
Function Main:Int()
    Local myList:List<Object> = New List<Object>
    
    Local myOne:one = New one
    myOne.name="Michael"
    myList.AddLast(Object(myOne))
    
    Local myTwo:two = New two
    myTwo.value=1966
    myList.AddLast(Object(myTwo))
    
    For Local li:= Eachin myList
        Select temp(li).type
            Case 1
                one(li).Output()
                one(li).out1()
            Case 2
                two(li).Output()
                two(li).out2()
        End
    Next
    Return 0
End
 

SLotman

Active member
3rd Party Module Dev
Joined
Jul 3, 2017
Messages
191
Yeah, that should work for ints, strings and all - But what I needed was just a way to store different classes :)
(Think if you kill a monster, I just take something out of the 'bag' to give to the player)
 

Phil7

Administrator
CX Code Contributor
3rd Party Tool Dev
Joined
Jun 26, 2017
Messages
681
Hmm, this sounds like the collections you have in Python. Could you explain what you want to use it for.
At the moment I don't see the use of different classes as they are all behaving as items you collect in your bag and not with the behaviour of their class type, right? If there was a collection of different types (classes), the moment you want to use its methods you would have to check what class it is to cast it properly. At this stage you could also just create an instance of that class or get one from a pool to have that type at hand.
Don't take this as a critique, I just want to understand the concept of your implementation.
 

dawlane

Well-known member
CX Code Contributor
Joined
Jun 21, 2017
Messages
895
The only way your going to store different classes is to derive your items from a base class, wrap one of the map containers using the base class into your own custom class to deal with adding and removing items. Then when you need to retrieve that data, you have to locate and retrieve the item back as a base class object where you then test for the correct type identifier to cast back. Personally I'd just use the classes in the Json module. You can create a Json object and add any Json value to it and communicate between Json object using Json strings. Any other no Json class then just needs to convert it's items into a Json object.
 
Last edited:

Gerry Quinn

Active member
Tutorial Author
Joined
Jun 24, 2017
Messages
163
Instead of deriving all classes from a base class, you could have them implement an interface. If it has no methods then I guess you just have to say Class MagicWand Implements IBaggable, and then MagicWand instances can be added to List<IBaggable>. The advantages of that over just using Object are probably only theoretical, though.

I'd have thought an Item base class would be a natural option in most cases where you are doing this kind of thing, though.
 
Top Bottom