Esta página aún no está traducida: se muestra la versión en inglés.
Herencia y composición
Los módulos se apoyan unos en otros, y nada de eso es herencia de clases. No hay un módulo base del cual derivar ni una jerarquía que extender: los módulos forman un grafo. Esta página explica qué significa aquí “herencia” y cuáles son los seis mecanismos que hacen ese trabajo en su lugar.
Qué significa aquí la herencia
La palabra abarca cuatro mecanismos distintos:
- Los RPC de una entidad son parte de la entidad. No existen en ningún otro lugar: ni en un padre ni en un registro compartido. Consulta Entity.
- Un preset es un paquete con nombre, no una clase base. Las estadísticas, las habilidades, los proyectiles, los generadores de botín y los objetos del mundo son presets de
entity: paquetes de aspectos que aplica una vista de entidad. Por eso viven en una sola página, Entity Presets, y no como cinco módulos. Aplicar un preset agrega aspectos; no coloca tu tipo por debajo de nada. - Para reemplazar un paso de la plataforma, pones un atributo en tu reemplazo. No heredas del nuestro: declaras el tuyo, y la versión se elige según una condición, con el comportamiento predeterminado de la plataforma como respaldo. Consulta Extensibility.
- Un módulo toma prestado otro a través de un decorador, que restringe o amplía la interfaz prestada, y la implementación detrás puede intercambiarse. El caso desarrollado es un chat dentro de una sala (room), en Groups.
No existe una jerarquía de clases de módulos, porque un árbol solo admite ramas y las funciones reales las atraviesan. El emparejamiento (matchmaking) reserva lugares en las salas; el botín coloca objetos a través del mapa; una tabla de clasificación se alimenta de un hook que se ejecuta al cerrarse una sala.
Los seis mecanismos
Cada uno se declara con un atributo junto a lo que compone: la misma regla declarativa que rige todo lo demás en el SDK.
Puntos de montaje, como en un sistema de archivos. Un módulo se monta en la raíz —y compone varias interfaces en una sola— o dentro de un espacio de nombres. Si un segundo módulo reclama un punto de montaje ocupado, se rechaza al montarlo, nunca en la primera llamada. El mecanismo está en Bajo el capó.
Visibilidad léxica. La visibilidad de los nombres sigue el anidamiento: una declaración global se ve dentro de un módulo, y una local nunca se filtra hacia arriba. Lo que un módulo emite es otra cuestión y se declara en su propio contrato: un módulo conoce solo los eventos que declaró o que se registraron con él.
Encapsulamiento como contrato. Un módulo nunca sabe quién lo llama ni para qué. Lo que expone y lo que emite es todo su contrato público, y nada de quien llama cambia su comportamiento, salvo los permisos otorgados a quien llama.
Reutilización mediante decoradores e inversión de control. Un módulo se refiere a otro a través de un decorador, en lugar de meterse dentro de él, y la implementación detrás de la interfaz puede intercambiarse. Este es el mecanismo que te permite reemplazar uno de nuestros módulos por el tuyo sin que se enteren los módulos que dependen de él.
Las declaraciones amplían la API. Declara un evento en un grupo y aparece group.Send.ChatMessage(…) con su contrato; declara los datos members y aparece un getter tipado. La declaración es la entrada de la generación de código, y por eso lo que versionas es la declaración, no el código generado.
Tres ejes de direccionamiento a partir de un solo módulo. Todas las instancias, una instancia y el administrador de una instancia son tres API distintas, no una API con un flag. Se detalla por completo en Groups.
Argumentos implícitos
Dentro de una entidad nunca pasas la entidad. El receptor, quien llama y el contexto se vinculan automáticamente, porque los tres ya quedan determinados por dónde se hizo la llamada y quién la hizo. El mecanismo está en RPC.