If scripts A and B both extend script C, do A and B share the same variable names of those from C?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By jancnahn

If scripts A and B both extend script C and var_c is a variable in the script C, is var_c used in A different from var_c used in B?

So my scripts A and B extend script C.
A and B represent different states in a finite statement machine.
For example, in the finite state machine demo that came with the initial installment of Godot (from Steam), say C is motion.gd and A, B are move.gd and jump.gd.

I’m introducing a variable var_c in C hoping that it is “shared” by A and B in the sense that if var_c is updated in state A and when I enter state B, I wish to access the updated value of var_c.

Unfortunately, it looks like var_c that I call in state A is independent of var_c called in state B. I might have made a mistake, but I want to know if it is true in general.

Are var_c used in A and var_c used in B the same? If they are different, how do I access one from the other? Like A.var_c and B.var_c?

Thank you.

:bust_in_silhouette: Reply From: deaton64

Hi,

I find that sometimes it’s easier to take things like this outside of your code and create a new project and test them out.
So I did that with what you were asking. It seems that you are correct.
I created a script called c, then two nodes a and b, with a.gd and b.gd that extends from c.gd.
When I change the value of the var c in a.gd it is not changed in b.gd.

You can access the “other” value of c like this:

print(get_node("../b").c)
get_node("../b").c = 1

That of course depends on what you have called your nodes. As I said, mine are called a & b.

Also, if you want to use a variable that is the same across all scripts, you might want to try using a Global variable. See here

:bust_in_silhouette: Reply From: archeron

I think you’re getting confused by what “extending” actually does. You’re thinking in the javascript OOP model, in which new object instances can be created from existing instances, but Godot follows a different model that’s implemented in most other languages (C++, Python, …).

In these programming languages, a class (which in Godot is is usually defined by a script) is a kind of template that tells the computer how to instantiate objects that belong to that class. The class itself doesn’t represent actual data, its just a description of what kind of data objects of that class will hold – in fact, the Godot documentation makes it clear that a class itself can’t hold any data members (while in C++, Python etc, there are class member variables - these don’t exist for Godot).

In practice, this means that you must instantiate a class, e.g. create an object based on the description the class provides, if you want to hold data. It’s the object that will hold the data, e.g. that holds actual values for all the properties/member variables you defined. Every object you instantiate has the same properties/member variables, but none of them are shared.

When you write

var lives_left := 5

outside of a function in a script, you don’t tell Godot to create a global variable lives_left and set it to 5; you’re telling Godot that when an object of this class / a node that uses this script gets instantiated, it will hold a property named lives_left that is initialized with the value 5. If you create two instances, there will be two such properties, both initialized to 5, both independent from each other.

When you extend a class, you’re basically just saying that “my new class will hold these new member variables / properties IN ADDITION to those of the base class”. But just because two classes A and B extend the same base class C, that doesn’t mean that objects of A and objects of B will magically share the actual data in the properties/member variables you defined in C. How could they? All you do with that is say that these objects will have properties that are named the same. Objects (instances) of A and B are fully independent; every instance (object) of class A you create has its own full set of member variables/properties.

If you want to share data between different objects, what deaton64 suggests works, but it leads to strong coupling between your objects - they need to know about each others names in the scene tree, and they need to know about their internal makeup. That might not be such a good idea if your project starts growing; because one important idea of object-oriented programming is to reduce the amount of knowledge any object has about other objects.

A better solution to share data between two objects a & b instantiated from classes/scripts A and B might be to create a third class/script C, create an instance c and pass this instance to objects a and b in the _ready-function of a Node that contains both a and b. This way, a and b don’t need any knowledge about each other’s names; in fact they don’t need any knowledge about each other’s existence at all - they just need to know that there is an object c, instantiated from class C, which they receive when their parent object enters the scene tree ; and that this object c holds shared data that they have access to. That seems like a cleaner design to me. You might also want to look up singletons, which are a somewhat easier but less flexible way to share data between different parts of your application. But watch out; singletons are basically “global variables” and as such should be used reluctantly and with care. They seem to be an easy solution to many problems, but again, they tend to lead to tighter coupling of different parts of your code if you don’t watch out, and that’s really something you want to avoid as much as possible.