Yep! What you're missing is that food
is a map. There's only one map in your code, and it lives on the Animal
object. When you write gorilla.food
, you're accessing that map on Animal
, because it has not been overridden on gorilla
. Same for zebra
, which also has not overridden food
. So in the end, Animal.food
, gorilla.food
, and zebra.food
are just three different ways to reference the same map.
Note that this is true for name
as well. You didn't override name
in zebra
, so zebra.name
is just another way to access Animal.name
. But you don't notice anything odd about this, because strings are immutable; you can't change a string (you can only replace it with a different string).
But maps are mutable. So, if you change a value within the map, you will see that change no matter how you access it.
The solution is to do like you did with name
: assign a different map to the instances, rather than just mutate the map that's already on the base class. In fact it might be better to use Animal.food = null
in your class, to remind you that each instance needs to get its own food map. Often this is done in some kind of factory function, like this:
Animal = {}
Animal.name = "unknown"
Animal.Make = function
noob = new self
noob.food = {}
return noob
end function
gorilla = Animal.Make
gorilla.food["Banana"] = "twice a day"
gorilla.food["Nuts"]="100g."
zebra = Animal.Make
print zebra.food // prints empty {}
print zebra.name // "unknown", as expected
Let me know if you have any questions!