Pregunta

¿Qué es la reflexión y por qué es útil?

Estoy particularmente interesado en Java, pero supongo que los principios son los mismos en cualquier idioma.

¿Fue útil?

Solución

El nombre reflexión se utiliza para describir el código que puede inspeccionar otro código en el mismo sistema (o a sí mismo).

Por ejemplo, digamos que tiene un objeto de un tipo desconocido en Java y le gustaría llamar a un método 'hacerAlgo' si existe alguno.El sistema de escritura estática de Java no está realmente diseñado para soportar esto a menos que el objeto se ajuste a una interfaz conocida, pero usando la reflexión, su código puede mirar el objeto y descubrir si tiene un método llamado "hacer algo" y luego llamarlo si querer.

Entonces, para darle un ejemplo de código de esto en Java (imagine que el objeto en cuestión es foo):

Method method = foo.getClass().getMethod("doSomething", null);
method.invoke(foo, null);

Un caso de uso muy común en Java es el uso con anotaciones.JUnit 4, por ejemplo, utilizará la reflexión para buscar en sus clases métodos etiquetados con la anotación @Test y luego los llamará cuando ejecute la prueba unitaria.

Hay algunos buenos ejemplos de reflexión para comenzar http://docs.oracle.com/javase/tutorial/reflect/index.html

Y finalmente, sí, los conceptos son bastante similares en otros lenguajes de tipos estáticos que admiten la reflexión (como C#).En lenguajes de tipado dinámico, el caso de uso descrito anteriormente es menos necesario (ya que el compilador permitirá que se llame a cualquier método en cualquier objeto, fallando en tiempo de ejecución si no existe), pero el segundo caso de buscar métodos que están marcados o trabajar de cierta manera todavía es común.

Actualización de un comentario:

La capacidad de inspeccionar el código en el sistema y ver los tipos de objetos no es la reflexión, sino que escribe la introspección.La reflexión es la capacidad de hacer modificaciones en tiempo de ejecución haciendo uso de la introspección.La distinción es necesaria aquí ya que algunos idiomas apoyan la introspección, pero no admiten la reflexión.Uno de esos ejemplos es C ++

Otros consejos

Reflexión es la capacidad de un lenguaje para inspeccionar y llamar dinámicamente clases, métodos, atributos, etc.en tiempo de ejecución.

Por ejemplo, todos los objetos en Java tienen el método getClass(), que le permite determinar la clase del objeto incluso si no lo sabe en el momento de la compilación (p. ej.si lo declaraste como Object) - esto puede parecer trivial, pero tal reflexión no es posible en lenguajes menos dinámicos como C++.Los usos más avanzados le permiten enumerar y llamar a métodos, constructores, etc.

La reflexión es importante ya que permite escribir programas que no tienen que "saber" todo en tiempo de compilación, lo que los hace más dinámicos, ya que se pueden vincular en tiempo de ejecución.El código se puede escribir en interfaces conocidas, pero se pueden crear instancias de las clases reales que se utilizarán mediante la reflexión de los archivos de configuración.

Muchos marcos modernos utilizan ampliamente la reflexión por esta misma razón.La mayoría de los demás lenguajes modernos también utilizan la reflexión, y en los lenguajes de scripting (como Python) están aún más estrechamente integrados, ya que se siente más natural dentro del modelo de programación general de esos lenguajes.

Uno de mis usos favoritos de la reflexión es el siguiente método de volcado de Java.Toma cualquier objeto como parámetro y utiliza la API de reflexión de Java para imprimir cada nombre y valor de campo.

import java.lang.reflect.Array;
import java.lang.reflect.Field;

public static String dump(Object o, int callCount) {
    callCount++;
    StringBuffer tabs = new StringBuffer();
    for (int k = 0; k < callCount; k++) {
        tabs.append("\t");
    }
    StringBuffer buffer = new StringBuffer();
    Class oClass = o.getClass();
    if (oClass.isArray()) {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("[");
        for (int i = 0; i < Array.getLength(o); i++) {
            if (i < 0)
                buffer.append(",");
            Object value = Array.get(o, i);
            if (value.getClass().isPrimitive() ||
                    value.getClass() == java.lang.Long.class ||
                    value.getClass() == java.lang.String.class ||
                    value.getClass() == java.lang.Integer.class ||
                    value.getClass() == java.lang.Boolean.class
                    ) {
                buffer.append(value);
            } else {
                buffer.append(dump(value, callCount));
            }
        }
        buffer.append(tabs.toString());
        buffer.append("]\n");
    } else {
        buffer.append("\n");
        buffer.append(tabs.toString());
        buffer.append("{\n");
        while (oClass != null) {
            Field[] fields = oClass.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                buffer.append(tabs.toString());
                fields[i].setAccessible(true);
                buffer.append(fields[i].getName());
                buffer.append("=");
                try {
                    Object value = fields[i].get(o);
                    if (value != null) {
                        if (value.getClass().isPrimitive() ||
                                value.getClass() == java.lang.Long.class ||
                                value.getClass() == java.lang.String.class ||
                                value.getClass() == java.lang.Integer.class ||
                                value.getClass() == java.lang.Boolean.class
                                ) {
                            buffer.append(value);
                        } else {
                            buffer.append(dump(value, callCount));
                        }
                    }
                } catch (IllegalAccessException e) {
                    buffer.append(e.getMessage());
                }
                buffer.append("\n");
            }
            oClass = oClass.getSuperclass();
        }
        buffer.append(tabs.toString());
        buffer.append("}\n");
    }
    return buffer.toString();
}

Usos de la reflexión

La reflexión se utiliza comúnmente en programas que requieren la capacidad de examinar o modificar el comportamiento en tiempo de ejecución de las aplicaciones que se ejecutan en la máquina virtual Java.Esta es una característica relativamente avanzada y sólo deben utilizarla desarrolladores que tengan un conocimiento sólido de los fundamentos del lenguaje.Con esa advertencia en mente, la reflexión es una técnica poderosa y puede permitir que las aplicaciones realicen operaciones que de otro modo serían imposibles.

Funciones de extensibilidad

Una aplicación puede hacer uso de clases externas definidas por el usuario creando instancias de objetos de extensibilidad utilizando sus nombres completos.Navegadores de clase y entornos de desarrollo visual Un navegador de clase necesita poder enumerar a los miembros de las clases.Los entornos de desarrollo visual pueden beneficiarse del uso de información de tipos disponible en la reflexión para ayudar al desarrollador a escribir el código correcto.Los depugadores y las herramientas de prueba los debuggentes deben poder examinar a los miembros privados en las clases.Los arneses de prueba pueden hacer uso de la reflexión para llamar sistemáticamente a un conjunto reconocible de API definidas en una clase, para garantizar un alto nivel de cobertura de código en un conjunto de pruebas.

Desventajas de la reflexión

La reflexión es poderosa, pero no debe usarse indiscriminadamente.Si es posible realizar una operación sin utilizar la reflexión, entonces es preferible evitar su utilización.Se deben tener en cuenta las siguientes preocupaciones al acceder al código mediante reflexión.

  • Gastos generales de rendimiento

Dado que la reflexión implica tipos que se resuelven dinámicamente, no se pueden realizar determinadas optimizaciones de la máquina virtual Java.En consecuencia, las operaciones reflectantes tienen un rendimiento más lento que sus contrapartes no reflectantes y deben evitarse en secciones de código que se llaman con frecuencia en aplicaciones sensibles al rendimiento.

  • Restricciones de seguridad

Reflection requiere un permiso de tiempo de ejecución que puede no estar presente cuando se ejecuta bajo un administrador de seguridad.Esta es una consideración importante para el código que debe ejecutarse en un contexto de seguridad restringido, como en un subprograma.

  • Exposición de partes internas

Dado que la reflexión permite que el código realice operaciones que serían ilegales en código no reflectante, como acceder a campos y métodos privados, el uso de la reflexión puede provocar efectos secundarios inesperados, que pueden hacer que el código sea disfuncional y destruir la portabilidad.El código reflectante rompe las abstracciones y, por lo tanto, puede cambiar el comportamiento con las actualizaciones de la plataforma.

fuente: La API de reflexión

¡La reflexión es un mecanismo clave para permitir que una aplicación o marco funcione con código que quizás ni siquiera se haya escrito todavía!

Tomemos, por ejemplo, su archivo web.xml típico.Esto contendrá una lista de elementos de servlet, que contienen elementos de clase de servlet anidados.El contenedor de servlet procesará el archivo web.xml y creará una nueva instancia de cada clase de servlet mediante reflexión.

Otro ejemplo sería la API de Java para análisis XML. (JAXP).Donde un proveedor de analizador XML está "conectado" a través de propiedades del sistema conocidas, que se utilizan para construir nuevas instancias mediante la reflexión.

Y finalmente, el ejemplo más completo es Primavera que utiliza la reflexión para crear sus beans y por su uso intensivo de proxies

No todos los idiomas admiten la reflexión, pero los principios suelen ser los mismos en los idiomas que la admiten.

La reflexión es la capacidad de "reflexionar" sobre la estructura de su programa.O más concreto.Para observar los objetos y clases que tiene y obtener mediante programación información sobre los métodos, campos e interfaces que implementan.También puedes mirar cosas como anotaciones.

Es útil en muchas situaciones.En cualquier lugar donde desee poder insertar clases dinámicamente en su código.Muchos mapeadores relacionales de objetos utilizan la reflexión para poder crear instancias de objetos desde bases de datos sin saber de antemano qué objetos van a utilizar.Las arquitecturas plug-in son otro lugar donde la reflexión es útil.Ser capaz de cargar código dinámicamente y determinar si hay tipos que implementen la interfaz correcta para usar como complemento es importante en esas situaciones.

Reflection permite la creación de instancias de nuevos objetos, la invocación de métodos y operaciones de obtención/establecimiento de variables de clase dinámicamente en tiempo de ejecución sin tener conocimiento previo de su implementación.

Class myObjectClass = MyObject.class;
Method[] method = myObjectClass.getMethods();

//Here the method takes a string parameter if there is no param, put null.
Method method = aClass.getMethod("method_name", String.class); 

Object returnValue = method.invoke(null, "parameter-value1");

En el ejemplo anterior, el parámetro nulo es el objeto sobre el que desea invocar el método.Si el método es estático, proporcione nulo.Si el método no es estático, al invocarlo deberá proporcionar una instancia de MyObject válida en lugar de nula.

Reflection también le permite acceder a miembros/métodos privados de una clase:

public class A{

  private String str= null;

  public A(String str) {
  this.str= str;
  }
}

.

A obj= new A("Some value");

Field privateStringField = A.class.getDeclaredField("privateString");

//Turn off access check for this field
privateStringField.setAccessible(true);

String fieldValue = (String) privateStringField.get(obj);
System.out.println("fieldValue = " + fieldValue);
  • Para la inspección de clases (también conocida como introspección) no es necesario importar el paquete de reflexión (java.lang.reflect).Se puede acceder a los metadatos de la clase a través de java.lang.Class.

Reflection es una API muy poderosa pero puede ralentizar la aplicación si se usa en exceso, ya que resuelve todos los tipos en tiempo de ejecución.

Ejemplo :
Tomemos, por ejemplo, una aplicación remota que le proporciona a su aplicación un objeto que obtiene utilizando sus métodos API.Ahora, según el objeto, es posible que necesite realizar algún tipo de cálculo.
El proveedor garantiza que el objeto puede ser de 3 tipos y debemos realizar el cálculo en función de qué tipo de objeto.
Por lo tanto, podríamos implementar en 3 clases, cada una de las cuales contiene una lógica diferente. Obviamente, la información del objeto está disponible en tiempo de ejecución, por lo que no se puede codificar estáticamente para realizar el cálculo, por lo que se utiliza la reflexión para crear una instancia del objeto de la clase que necesita para realizar el cálculo en función de Objeto recibido del proveedor.

Java Reflection es bastante potente y puede resultar muy útil.Java Reflection lo hace posible para inspeccionar clases, interfaces, campos y métodos en tiempo de ejecución, sin saber los nombres de las clases, métodos, etc.en tiempo de compilación.También es posible crear instancias de nuevos objetos, invocar métodos y obtener/establecer valores de campo mediante la reflexión.

Un ejemplo rápido de reflexión en Java para mostrarle cómo se ve el uso de la reflexión:

Method[] methods = MyObject.class.getMethods();

    for(Method method : methods){
        System.out.println("method = " + method.getName());
    }

Este ejemplo obtiene el objeto Clase de la clase llamada MyObject.Usando el objeto de clase, el ejemplo obtiene una lista de los métodos de esa clase, itera los métodos e imprime sus nombres.

Aquí se explica exactamente cómo funciona todo esto.

Editar:Después de casi 1 año, estoy editando esta respuesta porque, mientras leía sobre la reflexión, obtuve algunos usos más de Reflection.

  • Spring usa configuraciones de beans como:


<bean id="someID" class="com.example.Foo">
    <property name="someField" value="someValue" />
</bean>

Cuando el contexto Spring procese este elemento <bean>, utilizará Class.forName(String) con el argumento "com.example.Foo" para crear una instancia de esa clase.

Luego volverá a utilizar la reflexión para obtener el definidor apropiado para el elemento <propiedad> y establecerá su valor en el valor especificado.

  • Junit usa Reflection especialmente para probar métodos privados/protegidos.

Para métodos privados,

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

Para campos privados,

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

Según tengo entendido:

Reflection permite al programador acceder dinámicamente a las entidades del programa.es decir.Al codificar una aplicación, si el programador desconoce una clase o sus métodos, puede hacer uso de dicha clase dinámicamente (en tiempo de ejecución) mediante el uso de la reflexión.

Se utiliza con frecuencia en escenarios donde el nombre de una clase cambia con frecuencia.Si surge tal situación, al programador le resultará complicado reescribir la aplicación y cambiar el nombre de la clase una y otra vez.

En cambio, al utilizar la reflexión, es necesario preocuparse por un posible cambio de nombre de clase.

Reflexión es una API que se utiliza para examinar o modificar el comportamiento de métodos, clases, interfaces en tiempo de ejecución.

  1. Las clases requeridas para la reflexión se proporcionan en java.lang.reflect package.
  2. La reflexión nos brinda información sobre la clase a la que pertenece un objeto y también los métodos de esa clase que se pueden ejecutar utilizando el objeto.
  3. A través de la reflexión podemos invocar métodos en tiempo de ejecución independientemente del especificador de acceso utilizado con ellos.

El java.lang y java.lang.reflect Los paquetes proporcionan clases para la reflexión de Java.

Reflexión se puede utilizar para obtener información sobre:

  1. Clase El getClass() El método se utiliza para obtener el nombre de la clase a la que pertenece un objeto.

  2. Constructores El getConstructors() El método se utiliza para obtener los constructores públicos de la clase a la que pertenece un objeto.

  3. Métodos El getMethods() El método se utiliza para obtener los métodos públicos de la clase a la que pertenece un objeto.

El API de reflexión se utiliza principalmente en:

IDE (entorno de desarrollo integrado), p.Eclipse, MyEclipse, NetBeans, etc.
Herramientas de depuración y prueba, etc.

Ventajas de utilizar la reflexión:

Características de extensibilidad: Una aplicación puede hacer uso de clases externas definidas por el usuario creando instancias de objetos de extensibilidad utilizando sus nombres completos.

Herramientas de depuración y prueba: Los depuradores utilizan la propiedad de reflexión para examinar miembros privados de clases.

Desventajas:

Gastos generales de rendimiento: Las operaciones reflectantes tienen un rendimiento más lento que sus contrapartes no reflectantes y deben evitarse en secciones de código que se llaman con frecuencia en aplicaciones sensibles al rendimiento.

Exposición de internos: El código reflectante rompe las abstracciones y, por lo tanto, puede cambiar el comportamiento con las actualizaciones de la plataforma.

Árbitro: Reflexión de Java javarevisited.blogspot.in

Reflection es un conjunto de funciones que le permite acceder a la información de tiempo de ejecución de su programa y modificar su comportamiento (con algunas limitaciones).

Es útil porque le permite cambiar el comportamiento del tiempo de ejecución dependiendo de la metainformación de su programa, es decir, puede verificar el tipo de retorno de una función y cambiar la forma en que maneja la situación.

En C#, por ejemplo, puede cargar un ensamblado (un .dll) en tiempo de ejecución y examinarlo, navegar por las clases y realizar acciones de acuerdo con lo que encontró.También te permite crear una instancia de una clase en tiempo de ejecución, invocar su método, etc.

¿Dónde puede ser útil?No es útil siempre sino para situaciones concretas.Por ejemplo, puede usarlo para obtener el nombre de la clase para fines de inicio de sesión, para crear dinámicamente controladores para eventos de acuerdo con lo que se especifica en un archivo de configuración, etc.

ejemplo sencillo para la reflexión.En un juego de ajedrez, no sabes qué moverá el usuario en tiempo de ejecución.La reflexión se puede utilizar para llamar a métodos que ya están implementados en tiempo de ejecución.

public class Test {

    public void firstMoveChoice(){
        System.out.println("First Move");
    } 
    public void secondMOveChoice(){
        System.out.println("Second Move");
    }
    public void thirdMoveChoice(){
        System.out.println("Third Move");
    }

    public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { 
        Test test = new Test();
        Method[] method = test.getClass().getMethods();
        //firstMoveChoice
        method[0].invoke(test, null);
        //secondMoveChoice
        method[1].invoke(test, null);
        //thirdMoveChoice
        method[2].invoke(test, null);
    }

}

La reflexión es dejar que el objeto vea su apariencia.Este argumento no parece tener nada que ver con la reflexión.De hecho, esta es la capacidad de "autoidentificarse".

La reflexión en sí es una palabra para lenguajes que carecen de la capacidad de autoconocimiento y autodetección como Java y C#.Debido a que no tienen la capacidad de autoconocimiento, cuando queremos observar cómo se ve, debemos tener otra cosa para reflexionar sobre cómo se ve.Excelentes lenguajes dinámicos como Ruby y Python pueden percibir su propio reflejo sin la ayuda de otros individuos.Podemos decir que un objeto en Java no puede percibir cómo se ve sin un espejo, que es un objeto de la clase reflexión, pero un objeto en Python puede percibirlo sin un espejo.Por eso necesitamos reflexión en Java.

Sólo quiero agregar algún punto a todo lo que se mencionó.

Con API de reflexión puedes escribir universal toString() método para cualquier objeto.

Es útil para depurar.

Aquí hay algún ejemplo:

class ObjectAnalyzer {

   private ArrayList<Object> visited = new ArrayList<Object>();

   /**
    * Converts an object to a string representation that lists all fields.
    * @param obj an object
    * @return a string with the object's class name and all field names and
    * values
    */
   public String toString(Object obj) {
      if (obj == null) return "null";
      if (visited.contains(obj)) return "...";
      visited.add(obj);
      Class cl = obj.getClass();
      if (cl == String.class) return (String) obj;
      if (cl.isArray()) {
         String r = cl.getComponentType() + "[]{";
         for (int i = 0; i < Array.getLength(obj); i++) {
            if (i > 0) r += ",";
            Object val = Array.get(obj, i);
            if (cl.getComponentType().isPrimitive()) r += val;
            else r += toString(val);
         }
         return r + "}";
      }

      String r = cl.getName();
      // inspect the fields of this class and all superclasses
      do {
         r += "[";
         Field[] fields = cl.getDeclaredFields();
         AccessibleObject.setAccessible(fields, true);
         // get the names and values of all fields
         for (Field f : fields) {
            if (!Modifier.isStatic(f.getModifiers())) {
               if (!r.endsWith("[")) r += ",";
               r += f.getName() + "=";
               try {
                  Class t = f.getType();
                  Object val = f.get(obj);
                  if (t.isPrimitive()) r += val;
                  else r += toString(val);
               } catch (Exception e) {
                  e.printStackTrace();
               }
            }
         }
         r += "]";
         cl = cl.getSuperclass();
      } while (cl != null);

      return r;
   }    
}

De la documentación de Java página

java.lang.reflect El paquete proporciona clases e interfaces para obtener información reflexiva sobre clases y objetos.La reflexión permite el acceso programático a información sobre los campos, métodos y constructores de clases cargadas, y el uso de campos, métodos y constructores reflejados para operar en sus contrapartes subyacentes, dentro de restricciones de seguridad.

AccessibleObject permite la supresión de controles de acceso si es necesario ReflectPermission está disponible.

Las clases de este paquete, junto con java.lang.Class acomodar aplicaciones como depuradores, intérpretes, inspectores de objetos, navegadores de clases y servicios como Object Serialization y JavaBeans que necesitan acceso a los miembros públicos de un objeto de destino (según su clase de tiempo de ejecución) o a los miembros declarados por una clase determinada

Incluye la siguiente funcionalidad.

  1. Obteniendo objetos de clase,
  2. Examinar las propiedades de una clase (campos, métodos, constructores),
  3. Configurar y obtener valores de campo,
  4. Invocando métodos,
  5. Creando nuevas instancias de objetos.

Echa un vistazo a esto documentación enlace para los métodos expuestos por Class clase.

De esto artículo (por Dennis Sosnoski, presidente de Sosnoski Software Solutions, Inc) y este artículo (exploraciones-de-seguridad pdf):

Puedo ver desventajas considerables que los usos del uso de Reflection.

Usuario de Reflexión:

  1. Proporciona una forma muy versátil de vincular dinámicamente componentes del programa.
  2. Es útil para crear bibliotecas que trabajen con objetos de formas muy generales.

Desventajas de la reflexión:

  1. La reflexión es mucho más lenta que el código directo cuando se usa para acceder a campos y métodos.
  2. Puede oscurecer lo que realmente sucede dentro de su código.
  3. Omitir el código fuente puede crear problemas de mantenimiento.
  4. El código de reflexión también es más complejo que el código directo correspondiente.
  5. Permite la violación de las limitaciones clave de seguridad Java, como la protección de acceso a datos y la seguridad de los tipos.

Abusos generales:

  1. Carga de clases restringidas,
  2. Obtener referencias a constructores, métodos o campos de una clase restringida,
  3. Creación de nuevas instancias de objetos, invocación de métodos, obtención o configuración de valores de campo de una clase restringida.

Eche un vistazo a esta pregunta de SE sobre el abuso de la función de reflexión:

¿Cómo leo un campo privado en Java?

Resumen:

El uso inseguro de sus funciones realizado desde el código del sistema también puede llevar fácilmente a comprometer un modo de seguridad de Java.l. Así que utilice esta función con moderación

Como sugiere el propio nombre, refleja lo que contiene, por ejemplo, un método de clase, etc., además de proporcionar una función para invocar un método que crea una instancia dinámicamente en tiempo de ejecución.

Es utilizado por muchos marcos y aplicaciones bajo madera para invocar servicios sin conocer realmente el código.

Reflection tiene muchas usos.Con el que estoy más familiarizado es poder crear código sobre la marcha.

ES DECIR:Clases dinámicas, funciones, constructores: basados ​​en cualquier datos (resultados XML/Array/SQL/Hardoded/etc.)

Reflection le brinda la posibilidad de escribir código más genérico.Le permite crear un objeto en tiempo de ejecución y llamar a su método en tiempo de ejecución.Por lo tanto, el programa puede hacerse altamente parametrizado.También permite realizar una introspección del objeto y la clase para detectar sus variables y métodos expuestos al mundo exterior.

Quiero responder a esta pregunta con el ejemplo.En primer lugar Hibernate usos del proyecto Reflection API para generar CRUD declaraciones para salvar el abismo entre la aplicación en ejecución y el almacén de persistencia.Cuando las cosas cambian en el dominio, el Hibernate tiene que conocerlos para conservarlos en el almacén de datos y viceversa.

Alternativamente funciona Lombok Project.Simplemente inyecta código en el momento de la compilación, lo que da como resultado que el código se inserte en las clases de su dominio.(Creo que está bien para captadores y definidores)

Hibernate eligió reflection porque tiene un impacto mínimo en el proceso de construcción de una aplicación.

Y desde Java 7 tenemos MethodHandles, que funciona como Reflection API.En proyectos, para trabajar con registradores simplemente copiamos y pegamos el siguiente código:

Logger LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());

Porque en este caso es difícil cometer errores tipográficos.

Como creo que es mejor explicarlo con ejemplos y ninguna de las respuestas parece hacer eso...

Un ejemplo práctico de uso de reflexiones sería un servidor de lenguaje Java escrito en Java o un servidor de lenguaje PHP escrito en PHP, etc.Language Server le brinda a su IDE capacidades como autocompletar, saltar a la definición, ayuda contextual, tipos de sugerencias y más.Para que todos los nombres de etiquetas (palabras que se pueden autocompletar) coincidan cuando presionas, digamos, PESTAÑA y mostrar todas las sugerencias, el servidor de idiomas tiene que inspeccionar todo lo relacionado con la clase, incluidos sus bloques de documentos y miembros privados.Para eso necesita un reflejo de dicha clase.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top