Você já parou para pensar porque em algumas linguagens de programação precisamos declarar o tipo de dado que uma variável contém e em outras não? Chamamos essa diferença de tipos dinâmicos ou estáticos, e está ligado a como as linguagens de programação lidam com os dados do programa na memória do computador e definem o que pode ser feito com o dado sem causar erros na execução do programa.
Ao final deste post você irá entender a diferença entre tipagem dinâmica e estática, terá a capacidade de escolher qual se adequa melhor às necessidades do projeto, além de como usar tipos estáticos no GDScript.
Se você está interessado em aprender mais sobre a GDScript, meu guia de referência rápida é um bom ponto de partida. Ele fornece uma visão geral de como começar a escrever GDScript.
O que são tipos?
Antes de entendermos qual a diferença entre tipagem dinâmica e estática, precisamos entender o que são tipos. Em programação, os tipos se referem ao tipo de dado que uma variável contém. É através do tipo de dado que são definidas quais operações podem ser realizadas em uma variável. Muitas linguagens de programação definem alguns tipos básicos como string (texto), int (números inteiros), float (números decimais), bool (booleanos, verdadeiro ou falso), entre outros. Além disso, a partir destes tipos mais simples, podemos agrupá-los e criar tipos mais complexos.
O que é tipagem dinâmica e estática?
Quando dizemos que uma linguagem de programação é dinamicamente tipada, estamos dizendo que, podemos alterar o tipo de uma variável após ela ser declarada, além disso não precisamos declarar um tipo quando criamos a variável.
Isto não significa que a linguagem não tenha tipos, apenas que o tipo da variável será inferido durante a execução do programa. Essa característica, apesar de aumentar a velocidade de desenvolvimento, pode levar a erros que só serão percebidos quando o programa for executado. GDScript, por exemplo, é dinamicamente tipada.
Do outro lado da moeda temos as linguagens que são estaticamente tipadas. Essas são linguagens em que os tipos das variáveis devem ser definidos ao serem criadas, além disso, após declarada não é possível mudar o tipo de uma variável.
Dessa forma o tipo da variável pode ser forçado pelo compilador em linguagem compiladas, e em casos de linguagens interpretadas validadores podem ser usados para assegurar o tipo, isto facilita a detecção de erros simples mas que podem ser difíceis de serem identificados durante a execução do programa. C#, por exemplo, é estaticamente tipada.
Outro ponto é que uma linguagem pode ter a tipagem considerada forte ou fraca. Em linguagens com tipagem forte, o tipo da variável deve ser sempre declarado e a linguagem não realiza nenhuma forma de conversão de tipos. Já nas linguagens com tipagem fraca, declarar o tipo da variável se torna opcional e pode ocorrer a conversão entre tipos. Por exemplo, C# é uma linguagem com tipagem forte, enquanto GDScript possui uma tipagem fraca.
Quais as vantagens da tipagem estática na GDScript?
A Godot tem suporte oficialmente para C# e para GDScript, a linguagem proprietária da engine. Caso opte por trabalhar com C#, você não tem muita escolha, já que a linguagem é estaticamente tipada.
Porém, ao trabalhar com GDScript as coisas ficam mais interessantes, uma vez que a linguagem pode ser usada tanto com tipos dinâmicos ou estáticos. GDScript é uma linguagem dinâmica por natureza. Porém na Godot 3.1 foi adicionado suporte a tipos estáticos na linguagem, e o suporte tem sido melhorado desde então.
Ao escrever GDScript com tipos estáticos temos acesso a uma série de recursos que facilitam o desenvolvimento. Por exemplo, quando declaramos o tipo de uma variável o autocompletar do editor da Godot oferece opções melhores, já que é possível saber todos os métodos e propriedade que o tipo oferece.
Erros também podem ser detectados bem antes, uma vez que com tipos estáticos o tipo de uma variável não pode ser mudado, o editor consegue detectar com antecedência quando tentamos atribuir uma variável com dados do tipo errado.
Outra vantagem é que ao declarar o tipo de uma variável, o código tende a ser mais bem estruturado e se documentar sozinho. Além disso, variáveis com tipos expostas no editor só aceitam dados do tipo certo e as opções são filtradas automaticamente.
Por fim, desde a Godot 4.0, o uso de tipos estáticos permite que a engine otimize o código que escrevemos quando o projeto é compilado, ajudando na performance do jogo.
Como usar tipagem estática em GDScript?
Para declarar o tipo de uma variável basta adicionar : e o tipo depois do nome da variável, como no exemplo abaixo:
var character_portrait: Sprite2D var character_name: String var character_max_hit_points: int
A Godot também oferece uma maneira alternativa para declarar o tipo da variável, o que nos possibilita omitir o tipo, que será inferido pela engine quando ela for inicializada. Como no exemplo abaixo:
var max_hit_points := 100 # O tipo da variável é 'int' var walk_speed := 10.5 # O Tipo da variável é 'float'
O mesmo pode ser feito para os parâmetros de uma função. E para definir o tipo do retorno da função usamos ->, seguido do tipo. Caso a função não retorne nenhum dado devemos utilizar void. Como nos exemplos abaixo:
func sum(a: int, b: int) -> int: return a + b # Essa função não retorna nenhum valor func damage(amount: int) -> void: pass
A Godot oferece suporte a uma série de tipos diferentes que podem ser usados na tipagem estática como os tipos internos como int, float, String, bool, são alguns exemplos. Classes nativas como Node, Area2D, Camera2D, entre outras. Classes globais criadas utilizando class_name ou classe internar criadas utilizando class.
A Array também pode ter o seu tipo declarado, para isso devemos informar o tipo entre []. Com isso, a Array irá permitir apenas que dados deste tipo sejam guardados. Como no exemplo abaixo.
var scores: Array[int] = [10, 20, 30] var enemies: Array[Node2D] = [] var itens: Array[Item] = []
Já quando precisamos converter um tipo para outro podemos utilizar a palavra-chave as. Porém precisamos ficar atentos, pois caso o tipo da variável sendo convertido não seja compatível com a variável que receberá o resultado da conversão, o valor null será atribuído a variável. Como no exemplo abaixo:
# Vamos supor que temos um personagem, e o node raiz é do tipo 'CharacterBody2D' # Neste caso podemos converter o personagem para 'Node2D', já que 'CharacterBody2D' herda de 'Node2D' var character := node as Node2D # Agora, caso tenhamos uma classe chamada 'Character' que herde de 'CharacterBody2D' # Porém se o script que estiver no node não seja do tipo 'Character' o valor null será atribuido a variável var character := node as Character
Porém, em alguns casos a Godot ainda não permite que o tipo seja declarado. É o caso dos elementos individuais de uma Array, tipos aninhados ou o tipo de dicionários. Como nos exemplos abaixo.
# Nos casos abaixo a engine irá exibir um erro no editor var vehicles: Array = [$Truck: Truck, $Kart: Kart] var units: Array[Array[Unit]] var treasures: Dictionary[Vector2, Chest] = {}
Para mais detalhes e informações confira a documentação oficial da engine sobre tipagem estática.
Conclusão
Normalmente a escolha entre tipagem dinâmica ou estática depende da escolha da linguagem usada no projeto. Com GDScript podemos escolher uma forma que se enquadra melhor ao seu estilo ou da sua equipe.
Em geral, ao usar tipos dinâmicos no GDScript ganhamos velocidade no desenvolvimento, porém corremos o risco de criar bugs que só ocorrem durante a execução do projeto e que podem ser difíceis de serem identificados. Já com tipos estáticos, esses erros podem ser identificados ainda quando escrevemos o código, além disso criamos um código mais estruturado, bem documentado e a funcionalidade de autocompletar da engine se torna mais útil.
Eu prefiro usar tipos estáticos pelos motivos ditos anteriormente. Ainda assim, acredito que tipos dinâmicos têm espaço na criação de protótipos e jogos para game jams. A escolha final fica por conta de suas preferências e as necessidades do projeto.