Estático / Dinâmico vs Forte / Fraco

319

Vejo esses termos espalhados por toda parte na programação e tenho uma vaga noção do que eles significam. Uma pesquisa mostra que essas coisas foram solicitadas em todo o estouro da pilha. Tanto quanto sei, a digitação estática / dinâmica em idiomas é sutilmente diferente da digitação Forte / Fraca, mas essa diferença me escapa. Fontes diferentes parecem usar significados diferentes ou até mesmo usar os termos de forma intercambiável. Não consigo encontrar um lugar que fale sobre os dois e realmente explique a diferença. O que seria legal é se alguém pudesse explicar isso claramente aqui para mim e para o resto do mundo.

Dan Revell
fonte

Respostas:

423
  • A digitação estática / dinâmica é sobre quando as informações de tipo são adquiridas (em tempo de compilação ou em tempo de execução)

  • A digitação forte / fraca é sobre o quão estritamente os tipos são distinguidos (por exemplo, se o idioma tenta fazer uma conversão implícita de seqüências de caracteres em números).

Veja a página wiki para informações mais detalhadas.

Dario
fonte
7
A Wikipedia tem todas as respostas. Por que eu ainda não deparei com isso, não sei.
Dan Revell
31
É uma pena que muitos não estejam cientes de que a estática / dinâmica é outra coisa que forte / fraca ... Isso realmente salvaria algum viés e discussão.
dykam
10
Existem diferentes graus de "fraqueza de tipo". Um idioma fortemente tipado pode tentar conversões de strings para números. Por outro lado, o HyperTalk (um idioma que eu usei décadas atrás) era tão fracamente digitado que "12" + "34"seria igual "46", mas "12" + "34Q"seria igual "1234Q"[felizmente, alguém poderia escrever "12" & "34"se quisesse concatenação]. Curiosamente, as variáveis ​​que mantinham os números os armazenavam como flutuadores de precisão dupla, e a matemática nessas variáveis ​​usava os valores de ponto flutuante sem o uso de strings, mas não havia como perguntar se uma variável era uma string ou número.
precisa
9
@kittylyst Eu não posso ver onde esta resposta sugere que forte é sinônimo de estática
Pete
4
++ para (aproximadamente) definições de linha única.
JamesFaix 8/16
211

Você descobriu um ponto fraco na terminologia que os amadores usam para falar sobre linguagens de programação. Não use os termos digitação "forte" e "fraco" , porque eles não têm um significado técnico universalmente aceito. 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".

Tipagem forte geralmente significa que não há brechas no sistema de tipos, enquanto tipagem fraca significa que o sistema de tipos pode ser subvertido (invalidando quaisquer garantias). Os termos geralmente são usados ​​incorretamente para significar digitação estática e dinâmica. Para ver a diferença, pense em C: o idioma é verificado em tempo de compilação (digitação estática), mas há muitas brechas; você pode praticamente converter um valor de qualquer tipo para outro tipo do mesmo tamanho - em particular, pode converter livremente tipos de ponteiro. Pascal era uma linguagem que se destinava a ser fortemente tipada, mas que possuía uma brecha imprevista: um registro variante sem etiqueta.

As implementações de linguagens fortemente tipadas geralmente adquirem brechas ao longo do tempo, geralmente para que parte do sistema de tempo de execução possa ser implementada na linguagem de alto nível. Por exemplo, o Objective Caml tem uma função chamada Obj.magicque tem o efeito de tempo de execução de simplesmente retornar seu argumento, mas, em tempo de compilação, converte um valor de qualquer tipo em um de qualquer outro tipo. Meu exemplo favorito é o Modula-3, cujos designers chamaram de construção de modelagem LOOPHOLE.

Dito isto, você não pode contar com duas pessoas usando as palavras "forte" e "fraco" exatamente da mesma maneira. Então evite-os.

Norman Ramsey
fonte
31
(+1) para sua sugestão de evitar os termos "forte" e "fraco".
Nico
1
Concordo, estava apenas lendo o livro de Jon Skeet, e esta é a mesma resposta observada lá.
Bennett Yeates
Até onde eu sei, o Java também possui essas brechas, mas ainda é considerada uma linguagem de tipo forte, então acho que isso dá mais peso ao seu conselho de evitar os termos "forte" e "fraco".
doubleOrt
74

Basta colocar desta maneira: em um idioma estaticamente digitado, o tipo é estático , ou seja, depois de definir uma variável para um tipo, você NÃO PODE alterá-lo. Isso ocorre porque a digitação está associada à variável e não ao valor a que se refere.

Por exemplo em Java:

String str = "Hello";  //statically typed as string
str = 5;               //would throw an error since java is statically typed

Enquanto em um idioma digitado dinamicamente o tipo é dinâmico , ou seja, depois de definir uma variável para um tipo, você PODE alterá-lo. Isso ocorre porque a digitação está associada ao valor e não à variável.

Por exemplo, em Python:

str = "Hello" # it is a string
str = 5       # now it is an integer; perfectly OK

Por outro lado, a digitação forte / fraca em um idioma está relacionada a conversões implícitas de tipo (parcialmente extraídas da resposta de @ Dario):

Por exemplo, em Python:

str = 5 + "hello" 
# would throw an error since it does not want to cast one type to the other implicitly. 

enquanto no PHP:

$str = 5 + "hello"; // equals 5 because "hello" is implicitly casted to 0 
// PHP is weakly typed, thus is a very forgiving language.

A digitação estática permite verificar a correção do tipo no tempo de compilação. Os idiomas tipicamente estáticos são geralmente compilados e os idiomas dinamicamente são interpretados. Portanto, idiomas de tipo dinâmico podem verificar a digitação em tempo de execução.

mehmet
fonte
2
ótima resposta e parabéns por usar exemplos concretos.
Julian A.
3
É por isso que o PHP precisa ser usado com muito cuidado.
Ali Gajani
1
Os exemplos de idiomas são realmente úteis. Muito apreciado.
J Mullen
Nesse sentido, o Java seria ligeiramente digitado de maneira fraca, porque você pode concatenar não-strings com strings e por causa do unboxing / boxing automático?
Stephen Paul
1
@StephenPaul, você está certo, minha resposta pode ser entendida dessa maneira e não é esse o caso. Eu usei a concatenação por uma questão de simplicidade, mas, na verdade, força / fraqueza é sobre a conversão implícita de tipo da própria variável.
mehmet
20

Digitação fraca significa que o tipo de um objeto pode mudar dependendo do contexto. Por exemplo, em um idioma de tipo fraco, a cadeia "123" pode ser tratada como o número 123 se você adicionar outro número a ela. Exemplos de linguagens com digitação fraca são bash, awk e PHP.

Outro tipo de linguagem de tipo fraco é C, onde os dados em um endereço de memória podem ser tratados como um tipo diferente por conversão.

Em uma linguagem fortemente tipada, o tipo de um objeto não muda - um int é sempre um int e tentar usá-lo como uma string resultará em um erro. Java e Python são fortemente tipados.

A diferença entre a digitação dinâmica e a estática é quando as regras de tipo são aplicadas. Em uma linguagem de tipo estaticamente, o tipo de cada variável e parâmetro deve ser declarado na fonte e aplicado em tempo de compilação. Em um idioma digitado dinamicamente, os tipos são verificados apenas quando usados ​​em tempo de execução. Portanto, Java é digitado estaticamente e Python é digitado dinamicamente.

No entanto, os limites podem ser um pouco embaçados às vezes. Por exemplo, embora o Java seja digitado estaticamente, toda vez que você usa reflexão ou conversão (por exemplo, ao usar contêineres de Objetos), eles estão adiando a verificação de tipo para o tempo de execução.

Da mesma forma, os idiomas de tipo mais forte ainda serão convertidos automaticamente entre números inteiros e flutuantes (e, em alguns idiomas, BigInts com precisão abitrar).

Dave Kirby
fonte
1
Eu não posso concordar com esta frase -. "Em uma linguagem de tipo estaticamente, o tipo de cada variável e parâmetro deve ser declarado na fonte" - no SML, os tipos de variáveis ​​não precisam ser declarados (sempre que são verificados). Digamos que a função fuse argument x( fun f(x)) [**, portanto, nenhum tipo é declarado **] e o corpo da função é x+1. Sem nenhum tipo declarado, o compilador descobrirá que xdeve ser um int. - fun f x = x + 1; val f = fn : int -> int
Filip Bartuzi
Em relação a C, fundição não é contra tipagem forte, mas C permite a adição de tipos diferentes sem lançar também, por exemplo:5 + 'c' // OK
Mehmet
3
@ mehmet: em C, os valores dos caracteres estão no domínio inteiro, de modo que esse exemplo específico não viola a segurança do tipo. 'c' é apenas açúcar sintático para 99. C não tem um tipo de caractere dedicado.
precisa saber é o seguinte
Peter Lewerin: certo, eu deveria ter dado um exemplo melhor. Infelizmente, tem sido quase 20 anos desde que eu não toquei C :)
Mehmet
1
C não é um idioma de tipo fraco . É apenas que Java, C # etc. são linguagens de tipo mais forte em comparação com C. Leia mais aqui - en.wikipedia.org/wiki/Strong_and_weak_typing Se você verificar a definição de linguagem de tipo "fracamente", em seguida, linguagens de tipo "fracamente" são aqueles nos quais você pode fazer qualquer tipo de conversão, por exemplo, um int pode ser "implicitamente" convertido ou convertido em uma string, agora pense que isso é possível em C ou não?
hagrawal
15

Hoje, pesquisando sobre esse assunto, deparei-me com este ótimo artigo http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html Ele esclareceu muitas coisas para mim e pensei: isso pode adicionar algumas das grandes respostas acima.

Digitação forte e fraca:

Provavelmente, os sistemas de tipos mais comuns de classificação são "fortes" ou "fracos". Isso é lamentável, pois essas palavras quase não têm significado. É, até certo ponto, possível comparar duas linguagens com sistemas de tipos muito semelhantes e designar uma como tendo o mais forte desses dois sistemas. Além disso, as palavras não significam nada.

Tipos estáticos e dinâmicos

Essa é quase a única classificação comum de sistemas de tipos que tem significado real. De fato, seu significado é freqüentemente subestimado [...] sistemas dinâmicos e estáticos são duas coisas completamente diferentes, cujos objetivos se sobrepõem parcialmente.

Um sistema de tipos estáticos é um mecanismo pelo qual um compilador examina o código-fonte e atribui rótulos (chamados "tipos") a partes da sintaxe e os utiliza para inferir algo sobre o comportamento do programa. Um sistema de tipo dinâmico é um mecanismo pelo qual um compilador gera código para rastrear o tipo de dados (coincidentemente, também chamado de "tipo") usado pelo programa. O uso da mesma palavra "tipo" em cada um desses dois sistemas não é, é claro, inteiramente coincidente; ainda assim, é melhor entendido como tendo uma espécie de significado histórico fraco. Uma grande confusão resulta da tentativa de encontrar uma visão de mundo em que "tipo" realmente signifique a mesma coisa nos dois sistemas. Não faz.

Tipos explícitos / implícitos:

Quando esses termos são usados, eles se referem à extensão em que um compilador argumentará sobre os tipos estáticos de partes de um programa. Todas as linguagens de programação têm algum tipo de raciocínio sobre os tipos. Alguns têm mais que outros. ML e Haskell têm tipos implícitos, pois não são necessárias declarações de tipo (ou muito poucas, dependendo do idioma e das extensões em uso). Java e Ada têm tipos muito explícitos, e um está constantemente declarando os tipos de coisas. Todos os itens acima têm (relativamente, em comparação com C e C ++, por exemplo) sistemas estáticos fortes.

gonz
fonte
8

Em Scott's Programming Language Pragmatics , 3ª edição, página 291, temos

A verificação de tipo é o processo de garantir que um programa obedeça às regras de compatibilidade de tipo do idioma. Uma violação das regras é conhecida como conflito de tipo. Diz- se que um idioma é fortemente tipado se proíbe, de uma maneira que a implementação do idioma possa impor, a aplicação de qualquer operação a qualquer objeto que não se destina a suportar essa operação. Diz- se que um idioma é digitado estaticamente se for fortemente digitado e a verificação de tipo pode ser realizada em tempo de compilação. No sentido mais estrito do termo, poucas línguas são tipicamente estatizadas. Na prática, o termo é frequentemente aplicado a idiomas nos quais a maioria das verificações de tipo pode ser executada em tempo de compilação e o restante em tempo de execução.

Alguns exemplos: Ada é fortemente digitado e, na maioria das vezes, estaticamente (certas restrições de tipo devem ser verificadas em tempo de execução). Uma implementação de Pascal também pode fazer a maior parte de seu tipo de verificação em tempo de compilação, embora o idioma não seja fortemente tipado: registros de variantes sem marcação (a serem discutidos na Seção 7.3.4) são sua única brecha. O C89 é tipicamente significativamente mais fortemente tipado do que seus dialetos predecessores, mas ainda tipicamente menos fortemente tipificado que o Pascal. Suas brechas incluem uniões, sub-rotinas com números variáveis ​​de parâmetros e a interoperabilidade de ponteiros e matrizes (a ser discutida na Seção 7.7.1). Implementações de C raramente verificam qualquer coisa em tempo de execução.

A verificação de tipo dinâmico (tempo de execução) é uma forma de ligação tardia e tende a ser encontrada em idiomas que atrasam outros problemas até o tempo de execução também. Lisp e Smalltalk são digitados dinamicamente (embora fortemente). A maioria das linguagens de script também é digitada dinamicamente; alguns (por exemplo, Python e Ruby) são fortemente tipados. Os idiomas com escopo dinâmico geralmente são digitados dinamicamente (ou não são de todo): se o compilador não puder identificar o objeto ao qual um nome se refere, geralmente também não poderá determinar o tipo do objeto.

Portanto, em termos simples, a digitação estática / dinâmica se refere ao horário em que ocorre a verificação de tipo: tempo de compilação para digitação estática e tempo de execução para idiomas dinâmicos. Da mesma forma, a digitação forte / fraca refere-se à agressividade de um idioma na imposição de seu sistema de tipos.

Tentei traduzir a descrição de Scott em um bom diagrama, publicado abaixo.

O estático / dinâmico - plano de digitação forte / fraco

Evan Rosica
fonte
5

Eu acho que os outros colegas fizeram um bom trabalho, especialmente. explicando a diferença entre digitação estática e dinâmica. Mas no que diz respeito à digitação forte e fraca, deve-se dizer que existem diferentes entendimentos / visões.

Aqui estão dois exemplos:

  • Alguns dizem que Haskell é fortemente tipado, porque você não está autorizado a fazer qualquer tipo conversões.

  • Outros (por exemplo, a visão de Dario) dizem que um idioma que permite converter implicitamente de string para número de propósito é digitado de maneira fraca, mas outros chamam isso de digitação simples.

Ambas as declarações destacam não os extremos opostos de um sistema de tipos, mas aspectos completamente diferentes. Então, entendo a visão do Sr. Ramsey de não usar os termos "forte" e "fraco" para distinguir entre sistemas de tipos.

Nico
fonte
5

Linguagens de tipo dinâmico v / s estaticamente

  • Linguagens de tipo estático são aquelas em que a verificação de tipo é feita no momento da compilação, portanto, isso também significa que, em idiomas de tipo estaticamente, cada variável tem um tipo e não muda ao longo do curso. Agora, por outro lado, idiomas tipificados dinamicamente são aqueles em que a verificação de tipo é feita em tempo de execução e não há verificação de tipo em tempo de compilação, portanto, isso também significa que, em idiomas tipificados dinamicamente, pode ou não haver um tipo associado a uma variável e, se um tipo estiver associado, poderá ser um tipo genérico como "var" em JS, válido para uma sequência e um número.
    • “As implementações de linguagens dinamicamente verificadas por tipo geralmente associam cada objeto de tempo de execução a uma tag de tipo (ou seja, uma referência a um tipo) contendo suas informações de tipo. Essas informações de tipo de tempo de execução (RTTI) também podem ser usadas para implementar o envio dinâmico, ligação tardia, downcast, reflexão e recursos semelhantes. ”
  • Mesmo se o idioma for digitado estaticamente, ainda assim ele poderá ter algum recurso digitado dinamicamente, o que basicamente significa que algum tipo de verificação de tipo também será executada em tempo de execução. Isso é útil na conversão de tipos.
    • “Vários recursos úteis e comuns da linguagem de programação não podem ser verificados estaticamente, como downcast. Assim, muitos idiomas terão verificação de tipo estática e dinâmica; o verificador de tipo estático verifica o que pode e as verificações dinâmicas verificam o restante. "
  • “Alguns idiomas permitem escrever código que não é seguro para o tipo. Por exemplo, em C, programadores podem converter livremente um valor entre dois tipos que tenham o mesmo tamanho. ”
  • A vantagem das linguagens tipicamente "estaticamente" é que:
    • Como a maior parte da verificação de tipo é feita em tempo de compilação, o intérprete ou o tempo de execução podem ser executados a toda velocidade, sem se preocupar com os tipos.
    • Isso leva a um número menor de exceções de tempo de execução ou erros relacionados ao tipo, porque a maior parte da verificação do tipo é feita em tempo de compilação.
  • A vantagem das linguagens digitadas “dinamicamente” é que:
    • Eles podem ajudar na criação de protótipos extremamente rápida, já que o desenvolvedor não precisa entender o sistema de tipos para que o dev possa criar livremente variáveis ​​e executá-las, e isso leva a uma criação de protótipos muito rápida.
  • Lista de idiomas de forma estática e dinâmica :
    • Estatisticamente:
      • Java
      • C (C é uma linguagem de tipo estaticamente, mas menos "fortemente", em comparação com Java, porque permite conversões mais implícitas)
      • C ++
      • C #
    • Dinamicamente:
      • PERL
      • PHP
      • Pitão
      • Javascript
      • Rubi
  • A verificação de tipo é um importante recurso de segurança. Suponha que não haja verificação de tipo e um método aceite um objeto do tipo "BankAccount", que possui um método chamado "creditAccount (BankAccountDetails)", agora em tempo de execução, se não houver verificação de tipo, posso passar um objeto próprio classe que tem o mesmo método "creditAccount (BankAccountDetails)" e será executada, considerando que estamos falando de linguagem orientada a objetos porque o OOP suporta "polimorfismo" e aqui o que estamos discutindo é nada além de "polimorfismo". Portanto, basicamente uma linguagem orientada a objetos (que basicamente significa que suporta "polimorfismo") que não possui verificação de tipo forte pode levar a problemas de segurança.

Linguagens fortemente tipadas em v / s

  • Linguagens fortemente tipadas são aquelas nas quais conversões implícitas não são permitidas se houver perda de precisão. Por exemplo, em Java, você pode converter um "int to long" porque não há perda de precisão, mas não pode "implicitamente" converter um "long to int" porque haveria perda de precisão. Por outro lado, em linguagens com tipos fracos, conversões implícitas são permitidas mesmo se houver perda de precisão.
  • Eu acho que a linguagem digitada dinamicamente também pode ser uma linguagem fortemente tipada se "em tempo de execução" não permitir conversões implícitas nas quais há perda de precisão.

Boas leituras adicionais

hagrawal
fonte
você citou "agora em tempo de execução, se não houver verificação de tipo, posso passar um objeto da minha própria classe com o mesmo método" creditAccount (BankAccountDetails) "- se você já ultrapassou o mecanismo que poderia impedi-lo de passar um objeto em seguida, como a verificação de tipo que você vai parar de chamar esse método em caso de uma linguagem de tipagem estática?
Aseem Yadav
@AseemYadav O que você quer dizer com "* se você já ultrapassou o mecanismo que poderia ter impedido você de passar um objeto *"?
hagrawal
como você mencionou, é um importante recurso de segurança e também pode passar um objeto de sua própria classe com o mesmo método, portanto, implica que apenas parece uma vulnerabilidade quando você está tentando invadir o código de outra pessoa e se você está falando no contexto do código que pertence a você, é mais um problema de desempenho do que o relacionado à segurança, não é?
Aseem Yadav
Não há nenhum aspecto de desempenho, você deve vê-lo do contexto do polimorfismo para poder entender o aspecto de segurança. Mencionei isso no mesmo parágrafo.
hagrawal
1

Linguagens de tipo estaticamente geralmente exigem que você declare os tipos de variáveis, que são verificadas no momento da compilação para reduzir erros. A palavra "estático" em "estaticamente digitado" refere-se à "análise de código estático", que é o processo de examinar o código antes de executá-lo. Embora seja possível para uma linguagem de tipo estaticamente inferir o tipo da variável do lado direito de uma expressão ou parâmetros reais, na prática, a maioria das linguagens de tipo estaticamente exige que os tipos de variáveis ​​sejam declarados explicitamente.

Linguagens tipicamente dinamicamente geralmente não exigem que declarações de variáveis ​​tenham tipos e inferem tipos de variáveis ​​com base no tipo calculado como resultado da avaliação do lado direito de cada instrução de atribuição ou dos parâmetros reais de uma chamada de função. Como a variável pode receber várias atribuições ao longo da sua vida útil, seu tipo pode mudar com o tempo e é por isso que é chamada de "digitado dinamicamente". Além disso, o ambiente de tempo de execução precisa acompanhar o tipo atual de cada variável, para que o tipo seja vinculado ao valor e não com a declaração da variável. Isso pode ser considerado um sistema de informações de tipo de tempo de execução (RTTI).

Elementos de linguagens de tipo estático e dinâmico podem ser combinados. Por exemplo, o C # oferece suporte a variáveis ​​de tipo estático e dinâmico, e as linguagens orientadas a objetos geralmente oferecem suporte à baixa da hierarquia de tipos. As linguagens tipicamente estáticas geralmente fornecem várias maneiras de ignorar a verificação de tipo, por exemplo, usando conversão, reflexão e invocação dinâmica.

Digitação forte vs. fraca refere-se a um continuum de quanto a linguagem tenta evitar erros devido ao uso de uma variável como se fosse um tipo quando na verdade é outro tipo. Por exemplo, C e Java são linguagens de tipo estaticamente, no entanto, Java usa verificação de tipo muito mais forte do que C. O código C a seguir tem o prazer de compilar e executar e colocará um valor aleatório na variável b em tempo de execução, provavelmente causando um erro:

char *a = "123";
int b = (int)a;

O código Java equivalente produzirá um erro de compilação, o que geralmente é preferível:

String a = "123"
int b = (int)a;
Perigo
fonte