- Home /
Converting JS Array to Generic List
At the moment, due to legacy code, I have used JS arrays to build an array of subclasses. This is an example:
Superclass: Animal
Subclasses: Dog, Cat, Turtle
var Animals : Array;
class Animal{
var legs : int; //var shared between animals
}
class Dog extends Animal{
var bonesGathered : int; //var unique to Dog
}
class Cat extends Animal{
var whiskers : int; //var unique to Cat
}
class Turtle extends Animal{
var age : int; //var unique to Turtle
}
With JS Arrays, I can add the subclasses to the same array:
Animals.Push(new Dog());
Animals.Push(new Cat());
Animals.Push(new Turtle();
I'm trying to create better coding practices so I've read that JS arrays are typically poor design. I want to use Lists instead.
var Animals : List.<Animal>;
Animals.Add(new Dog());
Animals.Add(new Cat());
Animals.Add(new Turtle());
With Arrays, I was able to do
Animals[0].legs = 4;
Animals[0].bonesGathered= 12;
Animals[1].whiskers = 4;
Animals[2].age = 202;
How would I go about doing this with Lists? Attempting to do the same thing gives me an error of "bonesGathered" is not a member of "Animal". If it's not possible to keep them in the same array/list should I just stick with the Array? I need them to be in the same group, as I have a large portion of code that references this original JS Array. As I understand it currently the issue is because the compiler doesn't know the type at runtime, so there is an error when trying to change a subclass value when the item in the array/list is not of the same subclass. I'm not too sure as to why this is okay for an Array to determine the type at runtime and not for a List.
Answer by ShadyProductions · May 30, 2017 at 08:23 PM
use var Animals : List.<T>;
I am using that, I thought, with this:
var Animals : List.<Animal>;
Animals.Add(new Dog());
Animals.Add(new Cat());
Animals.Add(new Turtle());
And like I said Animals[0].bonesGathered does not work. Do you $$anonymous$$d explaining what I did incorrectly?
Answer by Bunny83 · May 30, 2017 at 11:06 PM
That's not possible. The only reason it is possible in UnityScript is because it allows dynamic typing which is extremely slow. When you use static typing you have to know the type in order to access class specific members.
In your example case the best solution would be to either implement a proper constructor or use a class initializer when you create the classes. I'm not sure if UnityScript actually supports class initializers but constructors will work
class Cat extends Animal{
var whiskers : int; //var unique to Cat
function Cat(aWhiskers : int)
{
whiskers = aWhiskers;
}
}
// [ ... ]
Animals.Add(new Cat(4));
Yes, constuctors work fine, I think. But if I wanted to read the amount of whiskers on the cat:
print("Animals[0].whiskers");
This wouldn't work, as "'whiskers' is not a member of 'Animals'". At least that is what my compiler says. Are you stating that this would be impossible to get from the Animals List? Hopefully I'm not confusing you too much, I really appreciate your help.
Consider C# since it is much less limited :P
Sorry but this project is very old and was written entirely in UnityScript. I am just looking for a way to make it more efficient without spending weeks rewriting all the scripts to C#. If there is no way to achieve this goal in UnityScript I am fine with leaving it the way it is, as it functions properly at runtime. $$anonymous$$y issue was that the compiler takes a long time since upgrading to Unity 5 and I suspected dynamic typing was the reason.
If you absolutely know that the animal at 0 is a cat, you can typecast it to a cat:
(Animals[0] as Cat).whiskers
Though I wonder, how do you absolutely know what type of animal is at what index?
Hey Bob,
Thanks for this! I didn't know I could typecast after the array like that. It definitely helped.
I absolutely know what type of animal it is at the index because of a switch statement looking for a variable of "animalType : String" in the Animal superclass. This was just an example piece of code as I didn't want to reveal my actual code but it worked the same nonetheless. Do you think I'm doing anything too inefficient from what you've noticed? I've actually managed to shave off roughly 8 seconds of compile time from this List issue scattered throughout my project. In total I had a 45 second compile time, now it's down to ~28. In Unity 4 it was only 12-13 seconds, without optimization.
Also, after using
Animals.Add(new Cat(4));
Would I be able to get the variable of whiskers from that List? Something like
var firstCatWhiskers : int = Animals[0].whiskers;
I'm assu$$anonymous$$g this isn't possible since you said that I can't even set the value, so getting it would lead to the same reasoning?