Estático / Dinámico vs Fuerte / Débil

319

Veo estos términos en todo el lugar en la programación y tengo una vaga noción de lo que significan. Una búsqueda me muestra que tales cosas se han preguntado en todo el desbordamiento de pila, de hecho. Por lo que sé, la escritura estática / dinámica en los idiomas es sutilmente diferente a la escritura fuerte / débil, pero esa diferencia se me escapa. Diferentes fuentes parecen usar diferentes significados o incluso usan los términos indistintamente. No puedo encontrar un lugar que hable sobre ambos y que realmente explique la diferencia. Lo que sería bueno es que alguien pueda explicar esto claramente aquí para mí y el resto del mundo.

Dan Revell
fuente

Respuestas:

423
  • La escritura estática / dinámica se trata cuando se adquiere información de tipo (ya sea en tiempo de compilación o en tiempo de ejecución)

  • La escritura fuerte / débil trata de cómo se distinguen estrictamente los tipos (por ejemplo, si el idioma intenta hacer una conversión implícita de cadenas a números).

Consulte la página wiki para obtener información más detallada.

Darío
fuente
77
Wikipedia tiene todas las respuestas. Por qué no me he topado con esto ya no lo sé.
Dan Revell
31
Es una pena que muchos no se den cuenta de que estático / dinámico es algo más que fuerte / débil ... Realmente ahorraría algo de sesgo y discusión.
Dykam
10
Hay diferentes grados de "debilidad tipo". Un lenguaje fuertemente tipado podría intentar conversiones de cadenas a números. Por otro lado, HyperTalk (un lenguaje que usé hace décadas) estaba tan débilmente escrito que "12" + "34"sería igual "46", pero "12" + "34Q"sería igual "1234Q"[afortunadamente, uno podría escribir "12" & "34"si quisiera concatenación]. Curiosamente, las variables que contienen números los almacenaron como flotantes de doble precisión, y las matemáticas en tales variables usaron los valores de punto flotante sin mezcla de cadenas, pero no había forma de preguntar si una variable era una cadena o un número.
supercat
99
@kittylyst No puedo ver dónde esta respuesta sugiere que fuerte es sinónimo de estática
Pete
44
++ para (aproximadamente) definiciones de una sola línea.
JamesFaix
211

Has descubierto un punto débil en la terminología que los aficionados usan para hablar sobre lenguajes de programación. No use los términos mecanografía "fuerte" y "débil" , porque no tienen un significado técnico universalmente acordado. Por el contrario, la escritura estática significa que los programas se verifican antes de ejecutarse , y un programa puede ser rechazado antes de que comience. La escritura dinámica significa que los tipos de valores se verifican durante la ejecución , y una operación mal escrita puede hacer que el programa se detenga o indique un error en el tiempo de ejecución . Una razón principal para la escritura estática es descartar programas que puedan tener tales "errores de tipo dinámico".

La tipificación fuerte generalmente significa que no hay lagunas en el sistema de tipos, mientras que la tipificación débil significa que el sistema de tipos puede subvertirse (invalidando cualquier garantía). Los términos a menudo se usan incorrectamente para significar tipeo estático y dinámico. Para ver la diferencia, piense en C: el lenguaje se verifica en el momento de la compilación (escritura estática), pero hay muchas lagunas; prácticamente puede emitir un valor de cualquier tipo a otro tipo del mismo tamaño, en particular, puede emitir tipos de puntero libremente. Pascal era un lenguaje que estaba destinado a ser fuertemente tipado, pero que tenía una escapatoria imprevista: un registro variante sin etiqueta.

Las implementaciones de lenguajes fuertemente tipados a menudo adquieren lagunas a lo largo del tiempo, generalmente para que parte del sistema de tiempo de ejecución se pueda implementar en el lenguaje de alto nivel. Por ejemplo, Objective Caml tiene una función llamada Obj.magicque tiene el efecto de tiempo de ejecución de simplemente devolver su argumento, pero en tiempo de compilación convierte un valor de cualquier tipo en uno de cualquier otro tipo. Mi ejemplo favorito es Modula-3, cuyos diseñadores llamaron a su construcción de fundición de tipos LOOPHOLE.

Dicho esto, no puede contar con dos personas que usen las palabras "fuerte" y "débil" exactamente de la misma manera. Así que evítalos.

Norman Ramsey
fuente
31
(+1) por su sugerencia para evitar los términos "fuerte" y "débil".
Nico
1
De acuerdo, estaba leyendo el libro de Jon Skeet, y esta es la misma respuesta observada allí.
Bennett Yeates
Hasta donde yo sé, Java también tiene estas lagunas, pero todavía se considera un lenguaje fuertemente tipado, así que supongo que esto le da más peso a su consejo de evitar los términos "fuerte" y "débil".
doubleOrt
74

En pocas palabras: en un lenguaje estáticamente escrito tipo estático , el tipo es estático , lo que significa que una vez que establece una variable en un tipo, NO PUEDE cambiarlo. Esto se debe a que la tipificación está asociada con la variable en lugar del valor al que se refiere.

Por ejemplo en Java:

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

Mientras que en un lenguaje de tipo dinámico, el tipo es dinámico , dinámico , lo que significa que después de establecer una variable en un tipo, PUEDE cambiarlo. Esto se debe a que la tipificación está asociada con el valor en lugar de la variable.

Por ejemplo en Python:

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

Por otro lado, el tipeo fuerte / débil en un idioma está relacionado con las conversiones de tipo implícito (en parte tomado de la respuesta de @ Dario):

Por ejemplo en Python:

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

mientras que en PHP:

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

La escritura estática permite verificar la corrección de tipo en tiempo de compilación. Los lenguajes tipados estáticamente generalmente se compilan, y los lenguajes tipados dinámicamente se interpretan. Por lo tanto, los idiomas escritos dinámicamente pueden verificar la escritura en tiempo de ejecución.

mehmet
fuente
2
gran respuesta, y felicitaciones por usar ejemplos concretos.
Julian A.
3
Es por eso que PHP debe usarse con mucho cuidado.
Ali Gajani el
1
Los ejemplos de lenguaje son realmente útiles. Muy apreciado.
J Mullen
En este sentido, ¿se escribiría Java de forma ligeramente débil porque puede concatenar cadenas sin cadenas y debido al auto-desempaquetado / boxeo?
Stephen Paul
1
@StephenPaul tienes razón, mi respuesta puede entenderse de esa manera, y ese no es el caso. Utilicé la concatenación en aras de la simplicidad, pero de hecho, la fortaleza / debilidad se trata de la conversión de tipo implícito de la variable en sí.
mehmet
20

La escritura débil significa que el tipo de un objeto puede cambiar según el contexto. Por ejemplo, en un idioma de tipo débil, la cadena "123" puede tratarse como el número 123 si le agrega otro número. Ejemplos de lenguajes con mecanografía débil son bash, awk y PHP.

Otro tipo de lenguaje débilmente tipado es C, donde los datos en una dirección de memoria pueden tratarse como un tipo diferente mediante conversión.

En un lenguaje fuertemente tipado, el tipo de un objeto no cambia: un int siempre es un int y tratar de usarlo como una cadena dará como resultado un error. Tanto Java como Python están fuertemente tipados.

La diferencia entre la escritura dinámica y la estática es cuando se aplican las reglas de escritura. En un lenguaje de tipo estático, el tipo de cada variable y parámetro debe declararse en la fuente y se aplica en tiempo de compilación. En un lenguaje de tipo dinámico, los tipos solo se verifican cuando se usan en tiempo de ejecución. Por lo tanto, Java se escribe estáticamente y Python se escribe dinámicamente.

Sin embargo, los límites pueden ser un poco borrosos a veces. Por ejemplo, aunque Java está estáticamente tipado, cada vez que usa la reflexión o un yeso (por ejemplo, cuando usa contenedores de objetos), difiere la verificación de tipo al tiempo de ejecución.

Del mismo modo, los idiomas más fuertemente tipados se convertirán automáticamente entre enteros y flotantes (y en algunos idiomas, BigInts de precisión arbitraria).

Dave Kirby
fuente
1
No puedo estar de acuerdo con esta oración. "En un lenguaje de tipo estático, el tipo de cada variable y parámetro debe declararse en la fuente": en SML no es necesario declarar los tipos de variables (independientemente de cómo se verifiquen). Digamos que la función ftoma el argumento x( fun f(x)) [** por lo que no se declaran tipos **] y el cuerpo de la función es x+1. Sin tipos declarados, el compilador descubrirá que xtiene que ser un int. - fun f x = x + 1; val f = fn : int -> int
Filip Bartuzi
Con respecto a C, el lanzamiento no está en contra de la tipificación fuerte, pero C permite agregar diferentes tipos sin lanzar también, por ejemplo:5 + 'c' // OK
mehmet
3
@mehmet: en C, los valores de los caracteres están en el dominio entero, por lo que ese ejemplo en particular no viola la seguridad de tipos. 'c' es solo azúcar sintáctico para 99. C no tiene un tipo de carácter dedicado.
Peter Lewerin
Peter Lewerin: correcto, debería haber dado un mejor ejemplo. Desafortunadamente, han pasado casi 20 años desde que no toqué C :)
mehmet
1
C no es un lenguaje débilmente escrito . Es solo que Java, C # etc. son lenguajes más fuertemente tipados en comparación con C. Lea más aquí: en.wikipedia.org/wiki/Strong_and_weak_typing Si verifica la definición de lenguaje tipeado "débilmente", entonces los idiomas tipeados "débilmente" son aquellos en los que puede hacer cualquier tipo de conversión, por ejemplo, un int se puede convertir "implícitamente" o convertir en una cadena, ahora piense que si esto es posible en C o no?
hagrawal
15

Hoy, al investigar sobre este tema, me encontré con este gran artículo http://blogs.perl.org/users/ovid/2010/08/what-to-know-before-debating-type-systems.html Aclaró un montón de cosas para mí y pensé que podría agregar a algunas de las excelentes respuestas anteriores.

Mecanografía fuerte y débil:

Probablemente, la forma más común de clasificar los sistemas de tipos es "fuerte" o "débil". Esto es lamentable, ya que estas palabras casi no tienen ningún significado. Es, hasta cierto punto, posible comparar dos idiomas con sistemas de tipos muy similares, y designar a uno como el más fuerte de esos dos sistemas. Más allá de eso, las palabras no significan nada en absoluto.

Tipos estáticos y dinámicos

Esta es casi la única clasificación común de sistemas de tipos que tiene un significado real. De hecho, su importancia es que con frecuencia se subestima [...] Los sistemas de tipo dinámico y estático son dos cosas completamente diferentes, cuyos objetivos se superponen parcialmente.

Un sistema de tipo estático es un mecanismo por el cual un compilador examina el código fuente y asigna etiquetas (llamadas "tipos") a partes de la sintaxis, y luego las usa para inferir algo sobre el comportamiento del programa. Un sistema de tipo dinámico es un mecanismo por el cual un compilador genera código para realizar un seguimiento del tipo de datos (casualmente, también llamado su "tipo") utilizado por el programa. El uso de la misma palabra "tipo" en cada uno de estos dos sistemas no es, por supuesto, realmente una coincidencia; sin embargo, se entiende mejor que tiene una especie de significación histórica débil. Se produce una gran confusión al tratar de encontrar una visión del mundo en la que "tipo" realmente signifique lo mismo en ambos sistemas. No lo hace.

Tipos explícitos / implícitos:

Cuando se usan estos términos, se refieren al grado en que un compilador razonará sobre los tipos estáticos de partes de un programa. Todos los lenguajes de programación tienen algún tipo de razonamiento sobre los tipos. Algunos tienen más que otros. ML y Haskell tienen tipos implícitos, ya que no se necesitan declaraciones de tipo (o muy pocas, dependiendo del idioma y las extensiones en uso). Java y Ada tienen tipos muy explícitos, y uno constantemente declara los tipos de cosas. Todos los anteriores tienen (relativamente, en comparación con C y C ++, por ejemplo) sistemas de tipo estático fuertes.

gonz
fuente
8

De Scott's Programming Language Pragmatics , tercera edición, página 291, tenemos

La verificación de tipos es el proceso de asegurar que un programa obedezca las reglas de compatibilidad de tipos del lenguaje. Una violación de las reglas se conoce como choque de tipos. Se dice que un lenguaje está fuertemente tipado si prohíbe, de una manera que la implementación del lenguaje pueda imponer, la aplicación de cualquier operación a cualquier objeto que no esté destinado a soportar esa operación. Se dice que un idioma está estáticamente tipado si está tipeado fuertemente y la verificación de tipo se puede realizar en tiempo de compilación. En el sentido más estricto del término, pocos idiomas están tipificados estáticamente. En la práctica, el término a menudo se aplica a los idiomas en los que la mayoría de las verificaciones de tipo se pueden realizar en tiempo de compilación, y el resto se puede realizar en tiempo de ejecución.

Algunos ejemplos: Ada está fuertemente tipado, y en su mayor parte estáticamente tipado (ciertas restricciones de tipo deben verificarse en tiempo de ejecución). Una implementación de Pascal también puede realizar la mayor parte de su verificación de tipos en tiempo de compilación, aunque el lenguaje no está muy bien tipeado: los registros de variantes sin etiquetar (que se discutirán en la Sección 7.3.4) son su única laguna. C89 está significativamente más fuertemente tipado que sus dialectos predecesores, pero todavía significativamente menos tipeado que Pascal. Sus lagunas incluyen uniones, subrutinas con números variables de parámetros y la interoperabilidad de punteros y matrices (que se discutirá en la Sección 7.7.1). Las implementaciones de C raramente verifican algo en tiempo de ejecución.

La comprobación dinámica de tipos (tiempo de ejecución) es una forma de enlace tardío y tiende a encontrarse en idiomas que retrasan otros problemas hasta el tiempo de ejecución también. Lisp y Smalltalk se escriben dinámicamente (aunque fuertemente). La mayoría de los lenguajes de script también se escriben dinámicamente; algunos (por ejemplo, Python y Ruby) están fuertemente tipados. Los lenguajes con alcance dinámico generalmente se escriben dinámicamente (o no se escriben en absoluto): si el compilador no puede identificar el objeto al que se refiere un nombre, generalmente tampoco puede determinar el tipo del objeto.

Entonces, en términos simples, la escritura estática / dinámica se refiere al momento en que ocurre la verificación de tipo: tiempo de compilación para la escritura estática y tiempo de ejecución para lenguajes dinámicos. Del mismo modo, la tipificación fuerte / débil se refiere a cuán agresivo es un lenguaje para hacer cumplir su sistema de tipos.

Intenté traducir la descripción de Scott en un bonito diagrama, que publiqué a continuación.

El plano de escritura estático / dinámico: fuerte / débil

Evan Rosica
fuente
5

Creo que los otros colegas hicieron un buen trabajo especialmente. explicando la diferencia entre tipeo estático y dinámico. Pero en lo que respecta a la tipificación fuerte y débil, se debe decir que hay diferentes entendimientos / puntos de vista.

Aquí dos ejemplos:

  • Algunos dicen que Haskell está fuertemente tipado, porque no está permitido realizar conversiones de ningún tipo.

  • Otros (por ejemplo, el punto de vista de Dario) dicen que un lenguaje que permite convertir implícitamente una cadena a un número a propósito está tipeado débilmente, pero incluso otros lo llaman simplemente tipear pato.

Ambas declaraciones destacan no los extremos opuestos de un sistema de tipos, sino aspectos completamente diferentes. Así que me uno a la opinión del Sr. Ramsey de no usar los términos "fuerte" y "débil" para distinguir entre sistemas de tipos.

Nico
fuente
5

Lenguajes estáticamente v / s escritos dinámicamente

  • Los idiomas de tipo estático son aquellos en los que la verificación de tipo se realiza en el momento de la compilación, por lo que esto también significa que en los idiomas de tipo estático cada variable tiene un tipo y no cambia a lo largo del curso. Ahora, en contraste, los idiomas de tipo dinámico son aquellos en los que la verificación de tipo se realiza en tiempo de ejecución, y no hay verificación de tipo en tiempo de compilación, por lo que esto también significa que en los idiomas de tipo dinámico puede o no haber un tipo asociado con una variable , y si un tipo está asociado, entonces podría ser un tipo genérico como "var" en JS, que es válido tanto para una cadena como para un número.
    • “Las implementaciones de lenguajes dinámicamente verificados por tipos generalmente asocian cada objeto de tiempo de ejecución con una etiqueta de tipo (es decir, una referencia a un tipo) que contiene su información de tipo. Esta información de tipo de tiempo de ejecución (RTTI) también se puede utilizar para implementar despacho dinámico, enlace tardío, conversión descendente, reflexión y características similares ".
  • Incluso si el idioma se escribe estáticamente, aún podría tener alguna característica escrita dinámicamente, lo que básicamente significa que también hay algún tipo de verificación de tipo en tiempo de ejecución. Esto es útil en la conversión de tipos.
    • "Una serie de características de lenguaje de programación útiles y comunes no se pueden verificar de forma estática, como la conversión descendente. Por lo tanto, muchos idiomas tendrán una comprobación de tipos tanto estática como dinámica; el verificador de tipo estático verifica lo que puede y las verificaciones dinámicas verifican el resto ".
  • “Algunos idiomas permiten escribir código que no es de tipo seguro. Por ejemplo, en C, los programadores pueden emitir libremente un valor entre dos tipos que tengan el mismo tamaño ".
  • La ventaja de los idiomas escritos "estáticamente" es que:
    • Dado que la mayor parte de la verificación de tipos se realiza en tiempo de compilación, el intérprete o el tiempo de ejecución pueden ejecutarse a toda velocidad, sin preocuparse por los tipos.
    • Conduce a un menor número de excepciones de tiempo de ejecución o errores relacionados con el tipo, porque la mayor parte de la verificación de tipo se realiza en tiempo de compilación.
  • La ventaja de los idiomas escritos "dinámicamente" es que:
    • Podrían ayudar en la creación de prototipos extremadamente rápida, ya que el desarrollador no necesita comprender el sistema de tipos para que el desarrollador pueda crear variables libremente y ejecutarlo, y esto conduce a una creación de prototipos muy rápida.
  • Lista de idiomas escritos de forma estática y dinámica :
    • Inactivamente:
      • Java
      • C (C es un lenguaje tipado estáticamente pero tipeado "fuertemente" en comparación con Java porque permite conversiones más implícitas)
      • C ++
      • C#
    • Dinamicamente:
      • PERL
      • PHP
      • Pitón
      • JavaScript
      • Rubí
  • La verificación de tipos es una característica de seguridad importante. Supongamos que no hay verificación de tipo, y un método acepta un objeto de tipo "BankAccount" que tiene un método llamado "creditAccount (BankAccountDetails)", ahora en tiempo de ejecución si no hay verificación de tipo, entonces puedo pasar un objeto propio clase que tiene el mismo método "creditAccount (BankAccountDetails)" y se ejecutará, considerando que estamos hablando del lenguaje orientado a objetos porque OOP admite "polimorfismo" y aquí lo que estamos discutiendo no es más que "polimorfismo". Entonces, básicamente un lenguaje orientado a objetos (que básicamente significa que admite "polimorfismo") que no tiene una verificación de tipo fuerte puede conducir a problemas de seguridad.

Lenguajes fuertemente t / v débilmente tipados

  • Los idiomas fuertemente tipados son aquellos en los que no se permiten conversiones implícitas si hay pérdida de precisión. Por ejemplo, en Java, puede emitir un "int a largo" porque no hay pérdida de precisión pero no puede "implícitamente" emitir un "largo a int" porque habría pérdida de precisión. Por el contrario, en lenguajes de tipo débil, las conversiones implícitas están permitidas incluso si hay pérdida de precisión.
  • Creo que el lenguaje escrito dinámicamente también puede ser un lenguaje fuertemente tipado si "en tiempo de ejecución" no permite conversiones implícitas en las que hay pérdida de precisión.

Buenas lecturas adicionales

hagrawal
fuente
usted citó "ahora en tiempo de ejecución si no hay verificación de tipo, entonces puedo pasar un objeto de mi propia clase que tiene el mismo método" creditAccount (BankAccountDetails) ", si ya ha superado el mecanismo que podría haberle impedido pasar un objeto entonces, ¿cómo la verificación de tipos le impedirá llamar a ese método en caso de un idioma estáticamente escrito?
Aseem Yadav
@AseemYadav ¿Qué quieres decir con "* si ya has superado el mecanismo que podría haberte impedido pasar un objeto *"?
hagrawal
como mencionó, es una característica de seguridad importante, y también que podría pasar un objeto de su propia clase con el mismo método, por lo que me implica que solo parece ser una vulnerabilidad cuando intenta ingresar al código de otra persona y Si está hablando en el contexto del código que le pertenece, es más un problema de rendimiento que el relacionado con la seguridad, ¿no es así?
Aseem Yadav
No tiene un aspecto de rendimiento, tiene que verlo desde el contexto del polimorfismo, entonces podrá comprender el aspecto de seguridad, lo he mencionado en el mismo párrafo.
hagrawal
1

Los lenguajes de tipo estático generalmente requieren que declare los tipos de variables, que luego se verifican en tiempo de compilación para reducir los errores. La palabra "estático" en "estáticamente tipado" se refiere al "análisis de código estático", que es el proceso de examinar el código antes de ejecutarlo. Aunque es posible que un lenguaje de tipo estático infiera el tipo de la variable desde el lado derecho de una expresión o parámetros reales, en la práctica la mayoría de los lenguajes de tipo estático requieren que los tipos de variables se declaren explícitamente.

Los lenguajes de tipo dinámico generalmente no requieren que las declaraciones de variables tengan tipos, e infieren tipos de variables basados ​​en el tipo calculado como resultado de evaluar el lado derecho de cada declaración de asignación o los parámetros reales de una llamada a función. Dado que a la variable se le pueden asignar múltiples tareas durante su vida útil, su tipo puede cambiar con el tiempo y es por eso que se llama "tipeado dinámicamente". Además, el entorno de tiempo de ejecución necesita realizar un seguimiento del tipo actual para cada variable, por lo que el tipo está vinculado al valor en lugar de a la declaración de la variable. Esto puede considerarse un sistema de información de tipo de tiempo de ejecución (RTTI).

Se pueden combinar elementos de lenguajes tipados estática y dinámicamente. Por ejemplo, C # admite variables tipadas estáticamente y dinámicamente, y los lenguajes orientados a objetos generalmente admiten la conversión descendente de la jerarquía de tipos. Los lenguajes de tipo estático suelen proporcionar varias formas de evitar la verificación de tipos, por ejemplo, mediante el uso de la conversión, la reflexión y la invocación dinámica.

Typing Strong vs. Weak Typing se refiere a un continuo de cuánto intenta el lenguaje evitar errores debido al uso de una variable como si fuera un tipo cuando en realidad es otro tipo. Por ejemplo, tanto C como Java son lenguajes de tipo estático, sin embargo, Java utiliza una verificación de tipos mucho más fuerte que C. El siguiente código C se compila y ejecuta, y pondrá un valor aleatorio en la variable b en tiempo de ejecución, lo que probablemente causará un insecto:

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

El código Java equivalente producirá un error de compilación, que generalmente es preferible:

String a = "123"
int b = (int)a;
Peligro
fuente