微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

龙目岛扩展方法:流行/优先级?

如何解决龙目岛扩展方法:流行/优先级?

首先:我非常喜欢龙目岛项目。很棒的工具!这个“编译时”库有很多优秀的方面。

喜欢 @ExtensionMethod,我已经多次点击这个“功能”,所以现在是我提出这个问题的时候了:

假设我有以下类:

@UtilityClass
public class AObject {
    static public String message(final Object pObject) {
        return "AObject = " + (pObject != null);
    }
}
@UtilityClass
public class AString {
    static public String message(final String pObject) {
        return "AString = " + (pObject != null);
    }
}
@ExtensionMethod({ AObject.class,AString.class })
public class Run_Object_String {
    public static void main(final String[] args) {
        System.out.println("\nRun_Object_String.main()");
        final String s = "Bier!";
        final Object o = new Object();

        System.out.println("Testing s: " + s.message());
        System.out.println("Testing o: " + o.message());
        System.out.println("Testing s: " + s.message());
    }
}
@ExtensionMethod({ AString.class,AObject.class })
public class Run_String_Object {
    public static void main(final String[] args) {
        System.out.println("\nRun_String_Object.main()");
        final String s = "Bier!";
        final Object o = new Object();

        System.out.println("Testing s: " + s.message());
        System.out.println("Testing o: " + o.message());
        System.out.println("Testing s: " + s.message());
    }
}
public class ClassprevalenceTest {
    public static void main(final String[] args) {
        Run_Object_String.main(args);
        Run_String_Object.main(args);
    }
}

输出

Run_Object_String.main()
Testing s: AObject = true
Testing o: AObject = true
Testing s: AObject = true

Run_String_Object.main()
Testing s: AString = true
Testing o: AObject = true
Testing s: AString = true
  • 这是为什么?
  • 为什么在第一个示例中没有调用 message(String),即使它比 message(Object) 具有更好的方法签名拟合​​?
  • 为什么 @ExtensionMethod 依赖于参数的顺序?

这是我盲目的假设:

  • 解析ExtensionMethods时,Lombok会从左到右处理注解值
    • 对于Run_Object_String,这意味着:首先是AObject,然后是AString
    • 对于Run_String_Object,这意味着:首先是AString,然后是AObject
  • Object-String:当将 AObject 修补到类 Run_Object_String 中时,将添加 message(Object) 方法。并且在使用 AString 方法修补 message(String) 时,不会添加它。 大概是因为 message(Object) 也匹配对 message(String)调用,所以不会添加 message(String)
  • String-Object:当将 AString 修补到类 Run_String_Object 中时,将添加 message(String) 方法。 当在 AObject 类中使用 message(Object) 打补丁时,旧的和​​现在的 message(String) 方法将不接受调用 message(Object),因此将添加方法 message(Object)

那么,除了非常注意添加 @UtilityClass 引用的顺序之外,还有其他解决方案吗?

  • Lombok 预处理器能否在添加扩展方法时进行扩展并使之更合理?
  • 你们对此有什么建议吗,或者对实际发生的事情的解释(与我的假设相反)

解决方法

这是我不知道的 Lombok 的一个迷人用法。我认为您可以深入寻找答案的最佳地点是来源本身,因为有关这项实验工作的文档似乎很简单,可以理解。

在此处查看 git:HandleExtensionMethod

根据逻辑,我猜测从注释中有效“拟合”正确方法的区域如下..

与其尝试“最佳”匹配,不如尝试“第一次”匹配。

也就是说,它似乎迭代 List<Extension> extensions。由于它是一个 Java 列表,我们假设按照扩展在原始注释中指定的顺序进行排序。

它似乎只是按照列表和 return 的顺序工作,只要某些内容与正确的方法和类型形状相匹配。

Types types = Types.instance(annotationNode.getContext());
        for (Extension extension : extensions) {
            TypeSymbol extensionProvider = extension.extensionProvider;
            if (surroundingTypeSymbol == extensionProvider) continue;
            for (MethodSymbol extensionMethod : extension.extensionMethods) {
                if (!methodName.equals(extensionMethod.name.toString())) continue;
                Type extensionMethodType = extensionMethod.type;
                if (!MethodType.class.isInstance(extensionMethodType) && !ForAll.class.isInstance(extensionMethodType)) continue;
                Type firstArgType = types.erasure(extensionMethodType.asMethodType().argtypes.get(0));
                if (!types.isAssignable(receiverType,firstArgType)) continue;
                methodCall.args = methodCall.args.prepend(receiver);
                methodCall.meth = chainDotsString(annotationNode,extensionProvider.toString() + "." + methodName);
                recursiveSetGeneratedBy(methodCall.meth,methodCallNode);
                return;
            }
        }

您可以查看其余代码以获取其他见解,因为那里似乎没有太多内容(即行数)可供查看,尽管不可否认,在该领域中这是一项令人印象深刻的壮举。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。