La diferencia es entre lo que es algo y cómo se comporta algo.
Muchos idiomas intentan combinar los dos, pero son cosas muy distintas.
Si cómo es qué, y qué es cómo ...
Si todo hereda de object
entonces, se producen algunos beneficios como: cualquier variable de objeto puede tener cualquier valor. Pero ese también es el problema, todo debe comportarse ( el cómo ) como un object
, y verse como ( el qué ) un object
.
Pero:
- ¿Qué pasa si su objeto no tiene una definición significativa de igualdad?
- ¿Qué pasa si no tiene un hash significativo?
- ¿Qué pasa si su objeto no puede ser clonado, pero los objetos sí pueden serlo?
O bien, el object
tipo se vuelve esencialmente inútil, debido a que el objeto no proporciona elementos comunes en todas las instancias posibles. O existirán objetos que tengan una definición rota / con cuernos de zapato / absurda de alguna supuesta propiedad universal encontrada en la object
cual se produce un comportamiento casi universal, excepto por una serie de trampas.
Si lo que no está relacionado con cómo
Alternativamente, puede mantener separados el Qué y el Cómo . Luego, varios tipos diferentes (sin nada en común en absoluto qué ) pueden comportarse de la misma manera que el colaborador ve cómo . En este sentido, la idea de un Iterator
no es un qué específico , sino un cómo . Específicamente, ¿ cómo interactúa con una cosa cuando aún no sabe con qué está interactuando?
Java (y similares) permiten enfoques para esto mediante el uso de interfaces. Una interfaz a este respecto describe los medios de comunicación e implícitamente un protocolo de comunicación y acción que se sigue. Cualquier Qué que se declare como de un Cómo dado , afirma que apoya la comunicación y la acción relevantes descritas por el protocolo. Esto permite a cualquier colaborador confiar en el Cómo y no atascarse al especificar exactamente qué se puede usar.
C ++ (y similares) permiten enfoques para esto escribiendo pato. A una plantilla no le importa si el tipo colaborador declara que sigue un comportamiento, solo que dentro de un contexto de compilación dado, con el objeto se puede interactuar de una manera particular. Esto permite que los punteros de C ++ y los objetos que anulan operadores específicos sean utilizados por el mismo código. Porque cumplen con la lista de verificación para ser considerados equivalentes.
- admite * a, a->, ++ a y a ++ -> iterador de entrada / reenvío
- admite * a, a->, ++ a, a ++, --a y a-- -> iterador bidireccional
El tipo subyacente ni siquiera tiene que estar iterando un contenedor, podría ser cualquier cosa . Además, permite que algunos colaboradores sean aún más genéricos, imaginen que una función solo necesita a++
, un iterador puede satisfacer eso, un puntero, un entero, cualquier objeto podría implementarse operator++
.
Especificación por debajo y por encima
El problema con ambos enfoques está por debajo y por encima de la especificación.
El uso de una interfaz requiere que el objeto declare que admite un comportamiento dado, lo que también significa que el creador debe imbuirlo desde el principio. Esto hace que algunos Qué no hagan el corte, ya que no lo declararon. También significa que siempre lo que tiene un antepasado común, la interfaz que representa el cómo . Esto vuelve al círculo del problema inicial de object
. Esto hace que los colaboradores especifiquen en exceso sus requisitos, mientras que simultáneamente hacen que algunos objetos sean inutilizables debido a la falta de declaración, o que se oculten las trampas ya que el comportamiento esperado está mal definido.
El uso de una plantilla requiere que el colaborador trabaje con un Qué completamente desconocido y, a través de sus interacciones, define un Cómo . Hasta cierto punto, esto dificulta la escritura de los colaboradores, ya que debe analizar el Qué para sus primitivas de comunicación (funciones / campos / etc.) mientras evita errores de compilación, o al menos señalar cómo un determinado Qué no cumple con sus requisitos para el Cómo . Esto permite que el colaborador requiera el mínimo absoluto de cualquier What , lo que permite el rango más amplio de lo que se utilizará. Desafortunadamente, esto tiene la desventaja de permitir usos sin sentido de objetos que técnicamente proporcionan las primitivas de comunicación para un determinadoCómo , pero no sigas el protocolo implícito que permite que ocurran todo tipo de cosas malas.
Iteradores
En este caso, una Iterator
es una ¿Cómo es la abreviatura de una descripción de la interacción. Cualquier cosa que coincida con esa descripción es, por definición, un Iterator
. Knowing How nos permite escribir algoritmos generales y tener una breve lista de ' Cómo ' se le da un Qué específico 'que se debe proporcionar para que el algoritmo funcione. Esa lista son las funciones / propiedades / etc, su aplicación tiene en cuenta la específica Lo que está siendo tratado por el algoritmo.