Qual é a diferença entre uma linguagem fortemente tipada e uma linguagem estaticamente tipada?


Respostas:


540

Qual é a diferença entre uma linguagem fortemente tipada e uma linguagem estaticamente tipada?

Uma linguagem de tipo estaticamente possui um sistema de tipos que é verificado no momento da compilação pela implementação (um compilador ou intérprete). A verificação de tipo rejeita alguns programas, e os programas que passam na verificação geralmente vêm com algumas garantias; por exemplo, o compilador garante não usar instruções aritméticas inteiras em números de ponto flutuante.

Não há um acordo real sobre o que significa "fortemente tipado", embora a definição mais amplamente utilizada na literatura profissional seja que, em uma linguagem "fortemente tipada", não seja possível ao programador contornar as restrições impostas pelo sistema de tipos . Esse termo é quase sempre usado para descrever linguagens de tipo estaticamente.

Estático vs dinâmico

O oposto de digitado estaticamente é "digitado dinamicamente", o que significa que

  1. Os valores usados ​​no tempo de execução são classificados em tipos.
  2. Existem restrições sobre como esses valores podem ser usados.
  3. Quando essas restrições são violadas, a violação é relatada como um erro do tipo (dinâmico).

Por exemplo, Lua , uma linguagem de tipo dinâmico, possui um tipo de sequência, um tipo numérico e um tipo booleano, entre outros. Em Lua, todo valor pertence a exatamente um tipo, mas isso não é um requisito para todas as linguagens dinamicamente digitadas. Em Lua, é permitido concatenar duas strings, mas não é permitido concatenar uma string e um booleano.

Forte vs fraco

O oposto de "fortemente tipado" é "pouco digitado", o que significa que você pode contornar o sistema de tipos. C é notoriamente digitado fracamente porque qualquer tipo de ponteiro é conversível em qualquer outro tipo de ponteiro simplesmente por conversão. O objetivo de Pascal era ser fortemente digitado, mas uma supervisão no design (registros de variantes sem marcação) introduziu uma brecha no sistema de tipos, de modo que tecnicamente é fracamente digitado. Exemplos de linguagens verdadeiramente fortemente tipadas incluem CLU, Standard ML e Haskell. De fato, o ML padrão passou por várias revisões para remover brechas no sistema de tipos que foram descobertas depois que o idioma foi amplamente implantado.

O que realmente está acontecendo aqui?

No geral, não é tão útil falar sobre "forte" e "fraco". Se um sistema de tipos possui uma brecha é menos importante que o número exato e a natureza das brechas, qual a probabilidade de surgir na prática e quais são as conseqüências da exploração de uma brecha. Na prática, é melhor evitar os termos "forte" e "fraco" por completo , porque

  • Os amadores freqüentemente os confundem com "estático" e "dinâmico".

  • Aparentemente, a "digitação fraca" é usada por algumas pessoas para falar sobre a prevalência relativa ou a ausência de conversões implícitas.

  • Os profissionais não podem concordar exatamente com o que os termos significam.

  • No geral, é improvável que você informe ou ilumine seu público.

A triste verdade é que, quando se trata de sistemas de tipos, "forte" e "fraco" não têm um significado técnico universalmente aceito. Se você deseja discutir a força relativa dos sistemas de tipos, é melhor discutir exatamente quais são as garantias e as que não são fornecidas. Por exemplo, uma boa pergunta a fazer é a seguinte: "é garantido que todo valor de um determinado tipo (ou classe) foi criado chamando um dos construtores desse tipo?" Em C, a resposta é não. Em CLU, F # e Haskell, é sim. Para C ++, não tenho certeza - gostaria de saber.

Por outro lado, a digitação estática significa que os programas são verificados antes de serem executados e um programa pode ser rejeitado antes de ser iniciado. A digitação dinâmica significa que os tipos de valores são verificados durante a execução e uma operação mal digitada pode fazer com que o programa pare ou sinalize um erro no tempo de execução. Um dos principais motivos da digitação estática é descartar programas que possam ter esses "erros de tipo dinâmico".

Um implica o outro?

Em um nível pedante, não, porque a palavra "forte" não significa realmente nada. Mas, na prática, as pessoas quase sempre fazem uma de duas coisas:

  • Eles (incorretamente) usam "forte" e "fraco" para significar "estático" e "dinâmico"; nesse caso, eles (incorretamente) usam "tipicamente fortemente" e "tipicamente estaticamente" de forma intercambiável.

  • Eles usam "forte" e "fraco" para comparar propriedades de sistemas do tipo estático. É muito raro ouvir alguém falar sobre um sistema dinâmico do tipo "forte" ou "fraco". Exceto por FORTH, que realmente não tem nenhum tipo de sistema de tipos, não consigo pensar em uma linguagem de tipo dinâmico em que o sistema de tipos possa ser subvertido. Por definição, essas verificações são transferidas para o mecanismo de execução e todas as operações são verificadas quanto à sanidade antes de serem executadas.

De qualquer forma, se uma pessoa chama um idioma "fortemente tipado", é muito provável que essa pessoa esteja falando sobre um idioma estaticamente digitado.


3
@ Adam: o suficiente Evidentemente não correta a ser upvoted :) Porque a resposta de Cletus contém tantos equívocos (embora eu editei o pior deles), senti-me compelido a soletrar tudo em palavras de uma sílaba ...
Norman Ramsey

1
Bem, eu votei em você :) Mesmo a palavra "compilar" não é clara com as VMs atuais executando linguagens dinâmicas. Tecnicamente, Java e C # são compilados duas vezes (JIT) e ambos fazem alguma análise de tipo. Uma linguagem como Javascript em execução no .NET vm pode ser mais Typesafe por causa da VM.
Adam Gent

2
Estou tão confuso agora! Ok, queridos grandes gladiadores da arena, uma alma pobre como eu pode seguir o seguinte entendimento simples? Os valores são associados ao tipo durante o tempo de compilação e não ao tempo de execução.2.Dinâmico: os valores são associados ao tipo durante o tempo de execução, portanto, o tipo do valor pode ser alterado durante o tempo de execução ~ mais propenso a problemas relacionados à conversão de tipos durante o tempo de execução. 3. Forte / fraco: esqueça! Estes não são termos técnicos e apenas nomenclatura ruim. Depende do contexto em que se está falando. Posso continuar minha vida com esse entendimento simples? :(
Saurabh Patil

"é garantido que todos os valores de um determinado tipo (ou classe) foram criados chamando um dos construtores desse tipo?" Em C a resposta é não. Alguém poderia fornecer um exemplo de situação em que isso ocorre em C? Suponho que envolve lançar ponteiros para estruturas?
Corazza 31/08/14

Digitação forte e fraca: não existe essa classificação.
Raúl

247

Isso geralmente é mal compreendido, então deixe-me esclarecer.

Digitação estática / dinâmica

A digitação estática é onde o tipo é vinculado à variável . Os tipos são verificados no momento da compilação.

A digitação dinâmica é onde o tipo está vinculado ao valor . Os tipos são verificados no tempo de execução.

Então, em Java, por exemplo:

String s = "abcd";

s"para sempre" será String. Durante sua vida útil, pode apontar para Strings diferentes (já que sé uma referência em Java). Pode ter um nullvalor, mas nunca se refere a um Integerou a List. Isso é digitação estática.

Em PHP:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

Isso é digitação dinâmica.

Digitação forte / fraca

(Editar alerta!)

Digitação forte é uma frase sem significado amplamente aceito. A maioria dos programadores que usam esse termo para significar algo diferente da digitação estática o utiliza para sugerir que existe uma disciplina de tipo imposta pelo compilador. Por exemplo, a CLU possui um sistema de tipos fortes que não permite que o código do cliente crie um valor do tipo abstrato, exceto usando os construtores fornecidos pelo tipo. C possui um sistema de tipos um tanto forte, mas pode ser "subvertido" até certo ponto, porque um programa sempre pode converter um valor de um tipo de ponteiro em um valor de outro tipo de ponteiro. Por exemplo, em C, você pode pegar um valor retornado malloc()e convertê-lo com alegria FILE*, e o compilador não tentará impedi-lo - nem avisará que você está fazendo algo desonesto.

(A resposta original dizia algo sobre um valor "não alterando o tipo em tempo de execução". Conheci muitos designers de linguagem e escritores de compiladores e não conheci um que falasse sobre valores que alteram o tipo em tempo de execução, exceto possivelmente algumas pesquisas muito avançadas sobre o tipo sistemas, onde isso é conhecido como "forte problema de atualização".)

A digitação fraca implica que o compilador não impõe um discpline de digitação ou talvez essa imposição possa ser facilmente subvertida.

O original dessa resposta combinava digitação fraca com conversão implícita (às vezes também chamada de "promoção implícita"). Por exemplo, em Java:

String s = "abc" + 123; // "abc123";

Este código é um exemplo de promoção implícita: 123 é convertido implicitamente em uma cadeia de caracteres antes de ser concatenado com "abc". Pode-se argumentar que o compilador Java reescreve esse código como:

String s = "abc" + new Integer(123).toString();

Considere um problema clássico do PHP "começa com":

if (strpos('abcdef', 'abc') == false) {
  // not found
}

O erro aqui é que strpos()retorna o índice da correspondência, sendo 0. 0 é coagido em booleano falsee, portanto, a condição é realmente verdadeira. A solução é usar em ===vez de ==evitar a conversão implícita.

Este exemplo ilustra como uma combinação de conversão implícita e digitação dinâmica pode levar os programadores a se perderem.

Compare isso com Ruby:

val = "abc" + 123

que é um erro de tempo de execução porque no Ruby o objeto 123 não é implicitamente convertido apenas porque é passado para um +método. No Ruby, o programador deve tornar a conversão explícita:

val = "abc" + 123.to_s

Comparando PHP e Ruby é uma boa ilustração aqui. Ambas são linguagens de tipo dinâmico, mas o PHP tem muitas conversões implícitas e o Ruby (talvez surpreendentemente se você não estiver familiarizado) não.

Estático / Dinâmico vs Forte / Fraco

O ponto aqui é que o eixo estático / dinâmico é independente do eixo forte / fraco. As pessoas provavelmente as confundem em parte porque a tipagem forte versus fraca não é apenas menos claramente definida, não há um consenso real sobre exatamente o que se entende por forte e fraco. Por esse motivo, a digitação forte / fraca é muito mais um tom de cinza do que preto ou branco.

Então, para responder à sua pergunta: outra maneira de analisar isso que é mais correto é dizer que a digitação estática é a segurança do tipo em tempo de compilação e a digitação forte é a segurança do tipo em tempo de execução.

A razão para isso é que as variáveis ​​em uma linguagem de tipo estaticamente têm um tipo que deve ser declarado e pode ser verificado em tempo de compilação. Uma linguagem de tipo forte possui valores que têm um tipo em tempo de execução, e é difícil para o programador subverter o sistema de tipos sem uma verificação dinâmica.

Mas é importante entender que um idioma pode ser Estático / Forte, Estático / Fraco, Dinâmico / Forte ou Dinâmico / Fraco.


Em vez de dizer que $ s é um número inteiro ou sequência, seria melhor se você dissesse que o tipo está associado ao "abcd" ou 1234 e não à variável $ s.
precisa saber é o seguinte

Excelente resposta com exemplos claros. No entanto, acho que isso não resolve completamente a confusão de por que as pessoas perguntam sobre forte / estático como um par duplo de conceitos. Por exemplo, a redação do OP de "a digitação estática IMPLICA digitação forte?" Sua resposta enfatiza a independência deles. Para continuar o esclarecimento de por que o forte é muitas vezes emparelhado com estática, resposta anterior de Norman Ramsey é muito bom: stackoverflow.com/questions/376611/...
JasDev

1
"abc" + 123é um erro de tempo de execução, não um erro de compilação no ruby. Se fosse um erro de compilação, o ruby ​​seria digitado estaticamente.
sepp2k

Os exemplos fracos de digitação precisam ser aprimorados (veja minha resposta), mas, de outro modo, uma formatação agradável.
Adam Gent

Na minha opinião, o tipo forte vs fraco é o seguinte: Strong: "c" + True = erro de tempo de execução ou erro de tempo de compilação. Fraco: "c" + True = "b" ou "d" porque tudo é tratado como bytes brutos. Strong: C #, Ruby, C ++ ruim: Assembly, C (devido a ponteiros void implícitos)
Jonathan Allen

17

Ambos são pólos em dois eixos diferentes:

  • fortemente tipado vs. fracamente tipado
  • digitado estaticamente vs. digitado dinamicamente

Com uma forte digitação , a não será convertido automaticamente de um tipo para outro. Digitando fracamente é o oposto: o Perl pode usar uma string como "123"em um contexto numérico, convertendo-a automaticamente no int 123. Uma linguagem fortemente tipada como python não fará isso.

Tipo estaticamente significa, o compilador descobre o tipo de cada variável no tempo de compilação. Linguagens dinamicamente digitadas apenas descobrem os tipos de variáveis ​​em tempo de execução.


6
Eu tenho que discordar. Uma linguagem fortemente tipada é aquela que sabe quais são os tipos em tempo de execução. Uma linguagem de tipo fraco é aquela que não gosta de Assembly. Seu exemplo está em um terceiro eixo, "conversões implícitas x explícitas".
Jonathan Allen

1
Na verdade normal, concordo com Jonathan, mas você não precisa ter os tipos disponíveis em tempo de execução para ser fortemente digitado se concluir a análise estática e não permitir a transmissão. (veja minha resposta editada).
Adam Gent

1
Python é um exemplo de tipagem dinâmica e uma linguagem fortemente digitado
MaRoBet

12

Fortemente digitado significa que há restrições entre conversões entre tipos. Digitar estaticamente significa que os tipos não são dinâmicos - você não pode alterar o tipo de uma variável depois que ela é criada.


Para demonstrar isso: Em um idioma fortemente tipado, você não pode comparar "5" == 5 e obtê-lo verdadeiro: seqüências de caracteres não são números inteiros. Se minha memória serve, a maioria das linguagens de script modernas são fortemente tipadas dinamicamente. Tcl / Tk, no entanto, é fracamente digitado - Tudo pode ser tratado como uma string.
Tabelas Pouco Bobby

Bobby, em um idioma fracamente digitado "5" == 5 é lido como 0x35 == 0x05. Ou, em outras palavras, tudo é tratado como bytes brutos.
Jonathan Allen

Eu tenho que discordar de vocês dois. Tome Lua; você pode comparar "5" == 5 e ele irá retornar falso, no entanto, uma rápida conversão pode ser feito indo "5" + 0.
RCIX

12

A coerção de dados não significa necessariamente um tipo fraco, porque às vezes seu açúcar sintático:

O exemplo acima de Java sendo digitado fracamente por causa de

String s = "abc" + 123;

Não é um exemplo de tipo fraco, porque realmente está fazendo:

String s = "abc" + new Integer(123).toString()

A coerção de dados também não é digitada de maneira fraca se você estiver construindo um novo objeto. Java é um exemplo muito ruim de digitação fraca (e qualquer linguagem que tenha boa reflexão provavelmente não será digitada de maneira fraca). Como o tempo de execução do idioma sempre sabe qual é o tipo (a exceção pode ser tipos nativos).

Isso é diferente de C. C é um dos melhores exemplos de tipagem fraca. O tempo de execução não faz ideia se 4 bytes é um número inteiro, uma estrutura, um ponteiro ou um caractere de 4 caracteres.

O tempo de execução da linguagem realmente define se é ou não digitado fracamente, ou se é realmente apenas uma opinião.

EDIT: Após uma reflexão mais aprofundada, isso não é necessariamente verdade, pois o tempo de execução não precisa ter todos os tipos reificados no sistema de tempo de execução para ser um sistema fortemente tipado. Haskell e ML têm uma análise estática tão completa que podem omitir informações do tipo em potencial no tempo de execução.


B é provavelmente um exemplo melhor, se um pouco menos conhecido.
Tom Hawtin - tackline

Javascript também é do tipo bastante fraco, mas porque existem poucos tipos e porque você não pode realmente construir novos tipos.
Adam Gent

9

A resposta já é dada acima. Tentando diferenciar entre forte vs semana e estático vs dinâmico conceito.

O que é VS fortemente digitado?

Tipo fortemente: não será convertido automaticamente de um tipo para outro

Em Go ou Python, como linguagens fortemente tipadas, "2" + 8 geram um erro de tipo, porque não permitem "coerção de tipo".

Digitado fracamente (vagamente): será automaticamente convertido em um tipo para outro: Idiomas de digitação fraca, como JavaScript ou Perl, não emitem um erro e, neste caso, o JavaScript resulta em '28' e o perl resulta em 10.

Exemplo Perl:

my $a = "2" + 8;
print $a,"\n";

Salve-o no main.pl e execute perl main.pl e você obterá a saída 10.

O que é do tipo Static VS Dynamic?

Na programação, o programador define digitação estática e dinâmica com relação ao ponto em que os tipos de variáveis ​​são verificados. Linguagens de tipo estático são aquelas em que a verificação de tipo é feita em tempo de compilação, enquanto as linguagens de tipo dinâmico são aquelas em que a verificação de tipo é feita em tempo de execução.

  • Estático: tipos verificados antes do tempo de execução
  • Dinâmico: tipos verificados em tempo real, durante a execução

O que isso significa?

No Go, as verificações digitadas antes do tempo de execução (verificação estática). Isso significa que ele não apenas converte e verifica o código que está executando, mas também examinará todo o código e o erro de tipo será gerado antes mesmo que o código seja executado. Por exemplo,

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

Salve este arquivo em main.go e execute-o, você receberá uma mensagem de falha na compilação para isso.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

Mas este caso não é válido para Python. Por exemplo, o seguinte bloco de código será executado na primeira chamada foo (2) e falhará na segunda chamada foo (0). É porque o Python é digitado dinamicamente, apenas converte e verifica o código de verificação em que está sendo executado. O bloco else nunca é executado para foo (2), então "2" + 8 nunca é visto e, para a chamada foo (0), ele tenta executar esse bloco e falhou.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

Você verá a seguinte saída

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects

8

Um não implica o outro. Para que um idioma seja estaticamente digitado , significa que os tipos de todas as variáveis ​​são conhecidos ou inferidos em tempo de compilação.

Um idioma fortemente tipado não permite que você use um tipo como outro. C é uma linguagem de tipo fraco e é um bom exemplo do que os idiomas de tipo forte não permitem. Em C, você pode passar um elemento de dados do tipo errado e ele não irá reclamar. Em idiomas fortemente tipados, você não pode.


7

A digitação forte provavelmente significa que as variáveis ​​têm um tipo bem definido e que existem regras estritas sobre a combinação de variáveis ​​de diferentes tipos nas expressões. Por exemplo, se A é um número inteiro e B é um flutuador, a regra estrita sobre A + B pode ser que A seja convertido em um flutuador e o resultado retornado como um flutuador. Se A for um número inteiro e B for uma sequência, a regra estrita poderá ser que A + B não seja válido.

A digitação estática provavelmente significa que os tipos são atribuídos no tempo de compilação (ou seu equivalente para linguagens não compiladas) e não podem ser alterados durante a execução do programa.

Observe que essas classificações não são mutuamente exclusivas, de fato, eu esperaria que elas ocorressem juntas com frequência. Muitas linguagens fortemente tipadas também são estaticamente.

E note que quando eu uso a palavra 'provavelmente' é porque não há definições universalmente aceitas desses termos. Como você já viu nas respostas até agora.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.