class can't be identified if typed after the caller class

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By roxasthewise
:warning: Old Version Published before Godot 3 was released.

Sorry if title a bit confusing.

So, i have 2 classes

Idle:

class IdleState:
	var player
	func _init(player):
		self.player = player
		pass
	
	func input(ev):
		if there is movement action detected
			exit()
		pass
	
	func exit():
		player.set_state(RunningState.new(player))
		pass

Running:

class RunningState:
	var player
	func _init(player):
		self.player = player
		pass
	
	func input(ev):
		if there is no movement detected
		     exit()
        pass
    	  	
    func exit():
    	player.set_state(IdleState.new(player))
    	pass

I got this error for those 2 classes:

Parser Error: Identifier not found: RunningState

If i type running state before the idle state, idle state can identify running state but running state can’t identify idle state. vice versa.
how do i get around this?

:bust_in_silhouette: Reply From: Adam Zahran

You shouldn’t have two classes depending on each other. Not in GDScript and not in any other language.
What I suggest you do instead. Is to have a state manager class that switches the state of the player when necessary. Or maybe just have the class called state and have attributes like idle, running, walking… etc.

class State:
    var player
    var state
    const IDLE = 0
    const RUNNING = 1
    func _init(player):
         self.player = player

    func set_running():
         state = RUNNING

Good design or not, the issue raised here is still relevant. In other languages it’s possible to reference class A in class B and vice-versa.

Zylann | 2016-11-25 19:44

This solution only allows for a closed set of states: you cannot extend your system with more states without adding more consts, boilerplate setter functions, and presumably dict entries to map the new states to their methods, or (god forbid) making an if-elif chain longer.

It also makes the case of parameterized states messier, as you will have to dump all the state-specific data into single class, and do something like

wall_direction = LEFT
set_wall_holding()

needlessly leaking data specific to wall-holding to every other state, and increasing the chances of undetected errors (like forgetting to set wall_direction, causing it to use some old value).

If you think of the states in an interfacey record-of-functions sort of way, there is nothing more wrong about the classes instancing each other than there is wrong with 5 - 3 equaling 2 and 2 + 3 equaling 5.

raymoo | 2016-12-11 04:53

Good design or not, the issue raised here is still relevant. In other
languages it’s possible to reference class A in class B and
vice-versa.

+1

snwflk | 2017-12-03 15:34