[RESOLVED] How to initialize an instance variable


This one makes no sense to me. I have a class called StateMachine with the following instance variable declaration.

ListStates !@states

In the instance constructor, I have the following.

println("StateMachine instance constructor")
@states : ListStates!

I have a pawn class named APOCCreature_Worker which has the following instance variable declaration.

StateMachine !@workerStateMachine

and its instance constructor has the following code.

println("APOCCreature_worker instance constructor")
@workerStateMachine : StateMachine!

When I run this code, I get the following in the log.

Member: Master.!() - Mind instance constructor called.
APOCCreature_worker instance constructor
StateMachine instance constructor
ListStates instance constructor

I forgot to mention that I subclassed List so I could add a custom constructor, which in this case just prints a line telling me the constructor ran. The pawn class is called from a SkookumScriptClassData component. So when I run this code in the PIE, it starts up just fine. When I stop the PIE, UE crashes hard. If I take out the @states : ListStates!, it runs just fine.

So just now I had the bright idea of trying this instead:

@states : ListStates!{}

And it seems to work. I’ve been banging my head against the List initialization for 2 days. Why does adding an empty set to the right of the ListStates constructor work? And why is something like that not necessary for other classes?


Sorry to hear that List initialization has been giving you such trouble.

It seems that you are working with 2 different bugs. :bug:

Bug 1: calling the superclass

You didn’t show the code for the ListStates constructor though I am guessing that it was missing a call to its superclass constructor? The constructor for List allocates memory and creates the internal structure to store a list. Its destructor would still be called and when it tries to clean up the list and deallocate the memory - it would definitely crash.

Here is an example constructor that calls the superclass List constructor.

  println("ListStates instance constructor") 

The @ is the SkookumScript scope resolution operator and it specifies the List version of the constructor so this method doesn’t just recursively call itself… The same thing in C++ for comparison is ::. The () is omitted since there are no arguments - List@!() would be the same.

The superclass constructor is not called automatically in SkookumScript since sometimes you don’t want to do the same behavior as the superclass and if you do want to call the superclass behavior you have the opportunity to have behavior before or after any call to the superclass. Obviously it still is pretty common to call the superclass and we may add some sort of warning in the SkookumScript parser if you create a constructor that does not call its superclass. We plan to extend the language so that superclass constructors (and destructors) will automatically be called if they are not called directly.

Bug 2: error in the {} item list literal

The list instantiation that has {} can be used to specify initial items such as ListStates!{'state1' 'state2'} however this is where you discovered a bug in our code. It seems that the item list {} version has a bug in that it doesn’t properly store the list type (it will always use List and not your subclass ListStates) and if any items are specified it doesn’t store them as expected. Definitely a horrible bug. Thank you for bringing it to our attention! I’ve fixed it locally and will be submitting the fix shortly.

Ironically the bug above wasn’t having the same crash that you initially experienced since it was creating a List object with a proper constructor call rather than a ListStates which did not have a call to the List constructor.

Other notes and tips on lists

List initialization can be tricky as far as its syntax is concerned since there is the type of the list, the type(s) of the items in the list and initial items in optional list literals.

You may want to specify the item type used in the instance variable declaration:

// list of type ListStates with items of type Symbol
ListStates{Symbol} !@states

Here are a bunch of ways to create/initialize a List:

// Simple list literals
{}        // empty with list type: List and item type: Object
{1 2}     // 2 items - Integer type inferred for items
{1 "hi"}  // 2 items - <Integer|String> type inferred

// Specify item type (using non list class)
// with `List` for list class type
Integer{}     // empty List of Integer objects
Integer{1 2}  // List of 2 Integer objects

// Create list of List type without item type specified
List!{}        // empty item list
List!{1 2}     // 2 items - Integer type inferred
List!{1 "hi"}  // 2 items - <Integer|String> type inferred

// Create list using empty item type specifier
List{}!{}        // empty item list
List{}!{1 2}     // 2 items - Integer type inferred
List{}!{1 "hi"}  // 2 items - <Integer|String> type inferred

// Create list with Integer item type specified
List{Integer}!{}                 // empty item list
List{Integer}!{1 2}              // 2 items
List{<Integer|String>}!          // can add String or Integer
List{<Integer|String>}!{1 2}     // 2 items, can add String
List{<Integer|String>}!{1 "hi"}  // 2 mixed Integer or String

// `List` can be replaced with any subclass of `List`.
// For example:
ListStates{Symbol}!                     // empty
ListStates!{'state1' 'state2'}          // 2 items type inferred
ListStates{Symbol}!{'state1' 'state2'}  // 2 items

If you have any additional questions on lists let me know and if you have any ideas on more ideal list syntax then please suggest away.

Great curated posts to learn about SkookumScript

Thanks! This a big help. You are quite correct that I wasn’t calling the super class constructor. Since there is no obvious code happening in the constructor when I view it in the IDE, I was expecting the underlying C++ code to initialize the storage.

I kind of feel a little happy that I helped you find a bug. :slight_smile: