org.apache.lucene.util

## Class VirtualMethod<C>

- java.lang.Object
- - org.apache.lucene.util.VirtualMethod<C>

-     public final class VirtualMethod<C>
      extends Object

  A utility for keeping backwards compatibility on previously abstract methods (or similar replacements).

  Before the replacement method can be made abstract, the old method must kept deprecated. If somebody still overrides the deprecated method in a non-final class, you must keep track, of this and maybe delegate to the old method in the subclass. The cost of reflection is minimized by the following usage of this class:

  Define static final fields in the base class (`BaseClass`), where the old and new method are declared:

        static final VirtualMethod<BaseClass> newMethod =
         new VirtualMethod<BaseClass>(BaseClass.class, "newName", parameters...);
        static final VirtualMethod<BaseClass> oldMethod =
         new VirtualMethod<BaseClass>(BaseClass.class, "oldName", parameters...);

  This enforces the singleton status of these objects, as the maintenance of the cache would be too costly else. If you try to create a second instance of for the same method/`baseClass` combination, an exception is thrown.

  To detect if e.g. the old method was overridden by a more far subclass on the inheritance path to the current instance's class, use a non-static field:

        final boolean isDeprecatedMethodOverridden =
         oldMethod.getImplementationDistance(this.getClass()) > newMethod.getImplementationDistance(this.getClass());

        // alternatively (more readable):
        final boolean isDeprecatedMethodOverridden =
         VirtualMethod.compareImplementationDistance(this.getClass(), oldMethod, newMethod) > 0

  `getImplementationDistance(java.lang.Class<? extends C>)` returns the distance of the subclass that overrides this method. The one with the larger distance should be used preferable. This way also more complicated method rename scenarios can be handled (think of 2.9 `TokenStream` deprecations).

  NOTE: This API is for internal purposes only and might change in incompatible ways in the next release.

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `VirtualMethod(Class<C> baseClass, String method, Class<?>... parameters)` Creates a new instance for the given `baseClass` and method declaration.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `static <C> int` | `compareImplementationDistance(Class<? extends C> clazz, VirtualMethod<C> m1, VirtualMethod<C> m2)` Utility method that compares the implementation/override distance of two methods.
    `int` | `getImplementationDistance(Class<? extends C> subclazz)` Returns the distance from the `baseClass` in which this method is overridden/implemented in the inheritance path between `baseClass` and the given subclass `subclazz`.
    `boolean` | `isOverriddenAsOf(Class<? extends C> subclazz)` Returns, if this method is overridden/implemented in the inheritance path between `baseClass` and the given subclass `subclazz`.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Constructor Detail

    - #### VirtualMethod

          public VirtualMethod(Class<C> baseClass,
                               String method,
                               Class<?>... parameters)

      Creates a new instance for the given `baseClass` and method declaration.
      Throws:
        `UnsupportedOperationException` - if you create a second instance of the same `baseClass` and method declaration combination. This enforces the singleton status.
        `IllegalArgumentException` - if `baseClass` does not declare the given method.

  - ### Method Detail

    - #### getImplementationDistance

          public int getImplementationDistance(Class<? extends C> subclazz)

      Returns the distance from the `baseClass` in which this method is overridden/implemented in the inheritance path between `baseClass` and the given subclass `subclazz`.
      Returns:
        0 iff not overridden, else the distance to the base class

    - #### isOverriddenAsOf

          public boolean isOverriddenAsOf(Class<? extends C> subclazz)

      Returns, if this method is overridden/implemented in the inheritance path between `baseClass` and the given subclass `subclazz`.

      You can use this method to detect if a method that should normally be final was overridden by the given instance's class.

      Returns:
        `false` iff not overridden

    - #### compareImplementationDistance

          public static <C> int compareImplementationDistance(Class<? extends C> clazz,
                                                              VirtualMethod<C> m1,
                                                              VirtualMethod<C> m2)

      Utility method that compares the implementation/override distance of two methods.
      Returns:
        - > 1, iff `m1` is overridden/implemented in a subclass of the class overriding/declaring `m2`
        - < 1, iff `m2` is overridden in a subclass of the class overriding/declaring `m1`
        - 0, iff both methods are overridden in the same class (or are not overridden at all)

Copyright © 2000-2021 Apache Software Foundation. All Rights Reserved.