Cuándo utilizar la información de tipo en tiempo de ejecución?
-
19-09-2019 - |
Pregunta
Si tengo varias subclases de algo, y un algoritmo que opera en los casos de estas subclases, y si el comportamiento del algoritmo varía ligeramente dependiendo de qué subclase particular, un ejemplo es, a continuación, la forma más habitual orientado a objetos para hacer esto es usar métodos virtuales.
Por ejemplo, si las subclases son nodos DOM, y si el algoritmo es para insertar un nodo hijo, que algoritmo difiere dependiendo de si el nodo padre es un elemento DOM (que puede tener hijos) o texto DOM (que no puede .): y así el método insertChildren
puede ser virtual (o extracto) en la clase base DomNode
, y puesto en práctica de manera diferente en cada una de las subclases DomElement
y DomText
Otra posibilidad es dar las instancias de una propiedad común, cuyo valor se puede leer: por ejemplo, el algoritmo puede leer la propiedad nodeType
de la clase base DomNode
; o para otro ejemplo, puede tener diferentes tipos (subclases) de paquetes de red, que comparten una cabecera de paquete común, y se puede leer el encabezado del paquete para ver qué tipo de paquete que es.
No he utilizado la información de tipo de tiempo de ejecución mucho más, incluyendo:
- Los
is
yas
palabras clave en C # - downcasting
- El método Object.GetType en punto net
- El operador
typeid
en C ++
Cuando estoy añadiendo un nuevo algoritmo que depende del tipo de subclase, tiendo en lugar de añadir un nuevo método virtual a la jerarquía de clases.
Mi pregunta es, ¿cuándo es apropiado utilizar la información de tipo de tiempo de ejecución, en lugar de las funciones virtuales?
Solución
Cuando no hay otra manera alrededor. métodos virtuales se prefieren siempre, pero a veces simplemente no se pueden utilizar. Hay dos razones por las cuales esto podría suceder, pero más común es que usted no tiene el código fuente de las clases que desea trabajar con o que no se pueden cambiar. Esto sucede a menudo cuando se trabaja con el sistema legado o con la biblioteca comercial de código cerrado.
En .NET Podría también ocurre que hay que cargar nuevos montajes sobre la marcha, como plugins y por lo general no tienen clases base, pero tienen que usar algo como la tipificación de pato.
Otros consejos
En C ++, entre algunos otros casos oscuros (que en su mayoría tienen que ver con las opciones de diseño inferiores), RTTI es una manera de poner en práctica la llamada múltiples métodos .
Este construcciones ( "es" y "como") son muy familiares para los desarrolladores de Delphi desde controladores de eventos por lo general los objetos abatidos a un ancestro común. Por ejemplo evento OnClick pasa el único remitente argurment: TObject independientemente del tipo del objeto, si se trata de TButton, TListBox o cualquier otro. Si quieres saber algo más acerca de este objeto que tiene que acceder a ella a través de "como", pero con el fin de evitar una excepción, se puede comprobar con "es" antes. Este downcasting permite un diseño de tipo de unión de los objetos y métodos que no podrían ser posibles con la comprobación estricta de tipo de clase. Imagínese que usted quiere hacer lo mismo si el usuario hace clic en el botón o el cuadro de lista, pero si nos proporcionan diferentes prototipos de funciones, que no podía ser posible ligarlos con el mismo procedimiento.
En el caso más general, un objeto puede llamar a una función que notifica que el objeto, por ejemplo, ha cambiado. Pero de antemano que deja el destino de la posibilidad de conocerlo "personalmente" (a través de como y lo es), pero no necesariamente. Esto se hace mediante el paso mismo como un ancestro más común de todos los objetos (TObject en caso de Delphi)
dynamic_cast <>, si no recuerdo mal, está en función de RTTI. Algunas interfaces externas oscuros también podrían depender de RTTI cuando un objeto pasa a través de un puntero nulo (por cualquier razón que podría suceder).
Una vez dicho esto, no he visto typeof () en estado salvaje en 10 años de trabajos de mantenimiento C ++ Pro. (Por suerte.)
Puede consultar más eficaz C # para un caso en tiempo de ejecución de la comprobación de tipos está bien.
Tema 3. especializarse algoritmos genéricos El uso de autonomía Tipo de Comprobación
Puede volver a utilizar fácilmente por los genéricos simplemente especificando nuevos parámetros de tipo. Una nueva creación de instancias con el nuevo tipo parámetros significa un nuevo tipo que tiene funcionalidad similar.
Todo esto es muy bueno, ya que escribe menos código. Sin embargo, a veces siendo más medios genéricos que no toman ventaja de una más específica, pero claramente superior, el algoritmo. La C# reglas del lenguaje tienen esto en cuenta. Sólo se necesita para que se den cuenta que su algoritmo puede ser más eficiente cuando los parámetros de tipo tener mayores capacidades, y luego a escribir ese código específico. Además, la creación de un segundo tipo genérico que especifica diferentes limitaciones no siempre funciona. Genérico ejemplificaciones se basan en el tiempo de compilación tipo de un objeto, y no el tipo de ejecución. Si usted no puede tener esto en cuenta, se puede perder posibles eficiencias.
Por ejemplo, supongamos que se escribe una clase que proporciona una enumeración de orden inversa en una secuencia de elementos representados a través IEnumerable
Pero, en general, usted debe considerar cuidadosamente tiempo de ejecución de la comprobación de tipos y asegurarse de que no viola Liskov Substituion principio.