static_typing.rst 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. .. _doc_gdscript_static_typing:
  2. Static typing in GDScript
  3. =========================
  4. In this guide, you will learn:
  5. - **How to use types in GDScript**
  6. - That **static types can help you avoid bugs**
  7. Where and how you use this new language feature is entirely up to you:
  8. you can use it only in some sensitive GDScript files, use it everywhere,
  9. or write code like you always did!
  10. Static types can be used on variables, constants, functions, parameters,
  11. and return types.
  12. .. note::
  13. Typed GDScript is available since Godot 3.1.
  14. A brief look at static typing
  15. -----------------------------
  16. With typed GDScript, Godot can detect even more errors as you write
  17. code! It gives you and your teammates more information as you're
  18. working, as the arguments' types show up when you call a method.
  19. Imagine you're programming an inventory system. You code an ``Item``
  20. node, then an ``Inventory``. To add items to the inventory, the people
  21. who work with your code should always pass an ``Item`` to the
  22. ``Inventory.add`` method. With types, you can enforce this:
  23. ::
  24. # In 'Item.gd'.
  25. class_name Item
  26. # In 'Inventory.gd'.
  27. class_name Inventory
  28. func add(reference: Item, amount: int = 1):
  29. var item = find_item(reference)
  30. if not item:
  31. item = _instance_item_from_db(reference)
  32. item.amount += amount
  33. Another significant advantage of typed GDScript is the new **warning
  34. system**. From version 3.1, Godot gives you warnings about your code as
  35. you write it: the engine identifies sections of your code that may lead
  36. to issues at runtime, but lets you decide whether or not you want to
  37. leave the code as it is. More on that in a moment.
  38. Static types also give you better code completion options. Below, you
  39. can see the difference between a dynamic and a static typed completion
  40. options for a class called ``PlayerController``.
  41. You've probably stored a node in a variable before, and typed a dot to
  42. be left with no autocomplete suggestions:
  43. .. figure:: img/typed_gdscript_code_completion_dynamic.png
  44. :alt: code completion options for dynamic
  45. This is due to dynamic code. Godot cannot know what node or value type
  46. you're passing to the function. If you write the type explicitly
  47. however, you will get all public methods and variables from the node:
  48. .. figure:: img/typed_gdscript_code_completion_typed.png
  49. :alt: code completion options for typed
  50. In the future, typed GDScript will also increase code performance:
  51. Just-In-Time compilation and other compiler improvements are already
  52. on the roadmap!
  53. Overall, typed programming gives you a more structured experience. It
  54. helps prevent errors and improves the self-documenting aspect of your
  55. scripts. This is especially helpful when you're working in a team or on
  56. a long-term project: studies have shown that developers spend most of
  57. their time reading other people's code, or scripts they wrote in the
  58. past and forgot about. The clearer and the more structured the code, the
  59. faster it is to understand, the faster you can move forward.
  60. How to use static typing
  61. ------------------------
  62. To define the type of a variable or a constant, write a colon after the
  63. variable's name, followed by its type. E.g. ``var health: int``. This
  64. forces the variable's type to always stay the same:
  65. ::
  66. var damage: float = 10.5
  67. const MOVE_SPEED: float = 50.0
  68. Godot will try to infer types if you write a colon, but you omit the
  69. type:
  70. ::
  71. var life_points := 4
  72. var damage := 10.5
  73. var motion := Vector2()
  74. Currently you can use three types of… types:
  75. 1. :ref:`Built-in <doc_gdscript_builtin_types>`
  76. 2. Core classes and nodes (``Object``, ``Node``, ``Area2D``,
  77. ``Camera2D``, etc.)
  78. 3. Your own custom classes. Look at the new :ref:`class_name <doc_gdscript_basics_class_name>`
  79. feature to register types in the editor.
  80. .. note::
  81. You don't need to write type hints for constants, as Godot sets it automatically from the assigned value. But you can still do so to make the intent of your code clearer.
  82. Custom variable types
  83. ~~~~~~~~~~~~~~~~~~~~~
  84. You can use any class, including your custom classes, as types. There
  85. are two ways to use them in scripts. The first method is to preload the
  86. script you want to use as a type in a constant:
  87. ::
  88. const Rifle = preload("res://player/weapons/Rifle.gd")
  89. var my_rifle: Rifle
  90. The second method is to use the ``class_name`` keyword when you create.
  91. For the example above, your Rifle.gd would look like this:
  92. ::
  93. extends Node2D
  94. class_name Rifle
  95. If you use ``class_name``, Godot registers the Rifle type globally in
  96. the editor, and you can use it anywhere, without having to preload it
  97. into a constant:
  98. ::
  99. var my_rifle: Rifle
  100. Variable casting
  101. ~~~~~~~~~~~~~~~~
  102. Type casting is a key concept in typed languages.
  103. Casting is the conversion of a value from one type to another.
  104. Imagine an Enemy in your game, that ``extends Area2D``. You want it to
  105. collide with the Player, a ``KinematicBody2D`` with a script called
  106. ``PlayerController`` attached to it. You use the ``on_body_entered``
  107. signal to detect the collision. With typed code, the body you detect is
  108. going to be a generic ``PhysicsBody2D``, and not your
  109. ``PlayerController`` on the ``_on_body_entered`` callback.
  110. You can check if this ``PhysicsBody2D`` is your Player with the ``as``
  111. casting keyword, and using the colon ``:`` again to force the variable
  112. to use this type. This forces the variable to stick to the
  113. ``PlayerController`` type:
  114. ::
  115. func _on_body_entered(body: PhysicsBody2D) -> void:
  116. var player := body as PlayerController
  117. if not player:
  118. return
  119. player.damage()
  120. As we're dealing with a custom type, if the ``body`` doesn't extend
  121. ``PlayerController``, the ``player``\ variable will be set to ``null``.
  122. We can use this to check if the body is the player or not. We will also
  123. get full autocompletion on the player variable thanks to that cast.
  124. .. note::
  125. If you try to cast with a built-in type and it fails, Godot will throw an error.
  126. .. _doc_gdscript_static_typing_safe_lines:
  127. Safe lines
  128. ^^^^^^^^^^
  129. You can also use casting to ensure safe lines. Safe lines are a new
  130. tool in Godot 3.1 to tell you when ambiguous lines of code are
  131. type-safe. As you can mix and match typed and dynamic code, at times,
  132. Godot doesn't have enough information to know if an instruction will trigger
  133. an error or not at runtime.
  134. This happens when you get a child node. Let's take a timer for example:
  135. with dynamic code, you can get the node with ``$Timer``. GDScript
  136. supports `duck-typing <https://stackoverflow.com/a/4205163/8125343>`__,
  137. so even if your timer is of type ``Timer``, it is also a ``Node`` and an
  138. ``Object``, two classes it extends. With dynamic GDScript, you also
  139. don't care about the node's type as long as it has the methods you need
  140. to call.
  141. You can use casting to tell Godot the type you expect when you get a
  142. node: ``($Timer as Timer)``, ``($Player as KinematicBody2D)``, etc.
  143. Godot will ensure the type works and if so, the line number will turn
  144. green at the left of the script editor.
  145. .. figure:: img/typed_gdscript_safe_unsafe_line.png
  146. :alt: Unsafe vs Safe Line
  147. Unsafe line (line 7) vs Safe Lines (line 6 and 8)
  148. .. note::
  149. You can turn off safe lines or change their color in the editor settings.
  150. Define the return type of a function with the arrow ->
  151. ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  152. To define the return type of a function, write a dash and a right angle
  153. bracket ``->`` after its declaration, followed by the return type:
  154. ::
  155. func _process(delta: float) -> void:
  156. pass
  157. The type ``void`` means the function does not return anything. You can
  158. use any type, as with variables:
  159. ::
  160. func hit(damage: float) -> bool:
  161. health_points -= damage
  162. return health_points <= 0
  163. You can also use your own nodes as return types:
  164. ::
  165. # Inventory.gd
  166. # Adds an item to the inventory and returns it.
  167. func add(reference: Item, amount: int) -> Item:
  168. var item: Item = find_item(reference)
  169. if not item:
  170. item = ItemDatabase.get_instance(reference)
  171. item.amount += amount
  172. return item
  173. Typed or dynamic: stick to one style
  174. ------------------------------------
  175. Typed GDScript and dynamic GDScript can coexist in the same project. But
  176. it's recommended to stick to either style for consistency in your codebase,
  177. and for your peers. It's easier for everyone to work together if you
  178. follow the same guidelines, and faster to read and understand other
  179. people's code.
  180. Typed code takes a little more writing, but you get the benefits we
  181. discussed above. Here's an example of the same, empty script, in a
  182. dynamic style:
  183. ::
  184. extends Node
  185. func _ready():
  186. pass
  187. func _process(delta):
  188. pass
  189. And with static typing:
  190. ::
  191. extends Node
  192. func _ready() -> void:
  193. pass
  194. func _process(delta: float) -> void:
  195. pass
  196. As you can see, you can also use types with the engine's virtual
  197. methods. Signal callbacks, like any methods, can also use types. Here's
  198. a ``body_entered`` signal in a dynamic style:
  199. ::
  200. func _on_Area2D_body_entered(body):
  201. pass
  202. And the same callback, with type hints:
  203. ::
  204. func _on_area_entered(area: CollisionObject2D) -> void:
  205. pass
  206. You're free to replace, e.g. the ``CollisionObject2D``, with your own type,
  207. to cast parameters automatically:
  208. ::
  209. func _on_area_entered(bullet: Bullet) -> void:
  210. if not bullet:
  211. return
  212. take_damage(bullet.damage)
  213. The ``bullet`` variable could hold any ``CollisionObject2D`` here, but
  214. we make sure it is our ``Bullet``, a node we created for our project. If
  215. it's anything else, like an ``Area2D``, or any node that doesn't extend
  216. ``Bullet``, the ``bullet`` variable will be ``null``.
  217. Warning system
  218. --------------
  219. .. note::
  220. Documentation about the GDScript warning system has been moved to
  221. :ref:`doc_gdscript_warning_system`.
  222. Cases where you can't specify types
  223. -----------------------------------
  224. To wrap up this introduction, let's cover a few cases where you can't
  225. use type hints. All the examples below **will trigger errors**.
  226. You can't use Enums as types:
  227. ::
  228. enum MoveDirection {UP, DOWN, LEFT, RIGHT}
  229. var current_direction: MoveDirection
  230. You can't specify the type of individual members in an array. This will
  231. give you an error:
  232. ::
  233. var enemies: Array = [$Goblin: Enemy, $Zombie: Enemy]
  234. You can't force the assignment of types in a ``for`` loop, as each
  235. element the ``for`` keyword loops over already has a different type. So you
  236. **cannot** write:
  237. ::
  238. var names = ["John", "Marta", "Samantha", "Jimmy"]
  239. for name: String in names:
  240. pass
  241. Two scripts can't depend on each other in a cyclic fashion:
  242. ::
  243. # Player.gd
  244. extends Area2D
  245. class_name Player
  246. var rifle: Rifle
  247. ::
  248. # Rifle.gd
  249. extends Area2D
  250. class_name Rifle
  251. var player: Player
  252. Summary
  253. -------
  254. Typed GDScript is a powerful tool. Available as of version 3.1 of Godot, it
  255. helps you write more structured code, avoid common errors, and
  256. create scalable systems. In the future, static types will also bring you
  257. a nice performance boost thanks to upcoming compiler optimizations.