Em um sistema digitado dinamicamente, os valores têm tipos em tempo de execução, mas variáveis e funções não. Em um sistema estaticamente digitado, variáveis e funções têm tipos conhecidos e verificados em tempo de compilação. Por exemplo, em Python x
pode ser qualquer coisa ; em tempo de execução, se é 1
um número e se é "foo"
, é uma string. Você só saberia qual tipo x
estava em tempo de execução e poderia ser diferente cada vez que você executava o programa. Em uma linguagem como Java, você escreveria int x
se x
fosse um número e saberia em tempo de compilação que x
sempre deve ser um int
.
Os tipos "explícito" e "implícito" referem-se a sistemas de tipos estáticos . A característica definidora de um sistema estático é que os tipos são conhecidos em tempo de compilação, mas não necessariamente que precisam ser gravados. Em Java, os tipos são explícitos - você precisa escrevê-los. Portanto, em Java, um método pode ser algo como:
public int foo(String bar, Object baz) { ... }
Os tipos são conhecidos no tempo de compilação (estático) e gravados (explícitos). No entanto, também existem idiomas que não o obrigam a escrever o tipo. Eles podem inferir o tipo de uma função do seu corpo e como ela é usada. Um exemplo seria OCaml, onde você pode escrever algo como:
let foo x = x + 1
Desde que você usou +
, o OCaml pode descobrir que x
deve ser um int
todo por si só. Portanto, o tipo de foo
( foo : int -> int
) é conhecido em tempo de compilação, assim como o exemplo de Java. É totalmente estático. No entanto, como o compilador pode descobrir quais são os tipos por conta própria, você não precisa escrevê-los: eles estão implícitos.
Em resumo: se um sistema de tipos é explícito ou implícito é uma propriedade de sistemas estáticos . É uma questão completamente diferente de saber se um sistema de tipos é dinâmico ou estático.
Freqüentemente, você tem sistemas de tipos que às vezes são explícitos e às vezes implícitos.
Por exemplo, acredito que o C # permite inferir tipos usando a var
palavra - chave. Portanto, em vez de escrever int x = 10
, você pode escrever var x = 10
e o compilador descobre que x
deve ser um int
. C ++ faz algo semelhante com auto
. Esses sistemas geralmente são explícitos, mas têm alguma inferência.
Por outro lado, existem sistemas geralmente implícitos, mas às vezes forçam você a escrever uma assinatura de tipo. Haskell é um ótimo exemplo. Na maioria das vezes, Haskell pode inferir os tipos para você. No entanto, às vezes você pode escrever um código ambíguo show . read
, onde Haskell não consegue descobrir os tipos por conta própria. Nesse caso, você seria forçado a especificar explicitamente o tipo de um show
ou de um read
. Além disso, alguns recursos mais avançados do sistema de tipos (como o polimorfismo rank-n) tornam a inferência indecidível - ou seja, não é garantido que ele seja interrompido. Isso significa que o código que usa esse recurso geralmente precisa de assinaturas de tipo explícitas.