当null作为参数传递时,Groovy选择了哪种重载方法? [英] What overloaded method is chosen by Groovy when null is passed as a parameter?

查看:165
本文介绍了当null作为参数传递时,Groovy选择了哪种重载方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  class SimpleTest {
void met(Object a){
printlnObject
}

void met String b){
printlnString
}

static main(args){
SimpleTest i = new SimpleTest()
i.met null)
}
}

此代码将产生输出Object 。它不会选择该方法的最专业版本。在这种情况下,String比Object更专业,所以这个规则不适用。

解决方案

Groovy使用距离计算方法。基本上,如果您将类和接口想象为图中的节点,并且它们通过继承关系进行连接,那么我们需要查找从给定参数类型(参数的运行时类型)到参数类型(静态键入方法参数has)。这些连接有不同的权重,基本上去超类意味着我想到的距离3,到接口1,包装原语也是1,vargs包装也有一个权重(并且不能真正在图中表示,所以抱歉有点失败的图像)



如果是null,这当然不能工作。这里我们将参数类型的距离改为Object。虽然非空的情况是我们最可能采用的特殊方法,但空白部分是最通用的方法。在Java中,您通常会使用静态类型或使用强制转换来确保要选择的内容。在Groovy中,我们没有静态类型,而最特殊的东西通常无法正确判断。因此,我们决定采用最一般的方法来代替这种情况。它一般工作得很好。

然后,对象有点像后备,允许您集中空处理。在未来的版本中,我们可能允许使用显式的null类型,如果存在,那么它将优先于Object。



虽然您经常可以直接看到类的距离方法,它对接口来说更复杂一些。基本上算法是这样的:如果我的当前类直接实现了我们正在寻找的接口,那么它与距离1匹配。如果类实现的任何接口都有我们寻找父接口的接口,则将啤酒花,直到我们在那里的距离。但我们寻找最短的距离。所以我们在超类中也是这样。从那里的任何搜索结果将有距离+1(对于超类跳跃)。如果超类搜索的距离比实现接口上的搜索更短,则将取而代之使用超类搜索结果。



至于用接口处理null ...如果接口不扩展另一个,到Object的距离在这里为1。如果是,则它是父接口+1的距离。如果扩展了多个接口,那么它又是最短路径。



让我们看看List和Integer for null。

List扩展Collection,Collection扩展Iterable,Iterable没有父类。对于Iterable来说,距离为1,对于Collection为2,最后为List 3。
整数扩展数字,数字扩展对象。由于我们跳了两次,我们在这里的距离是6(2x3),比另一个情况大得多。是的,这意味着我们更喜欢接口。实际上,我们这样做是出于实际的原因,因为这样证明是最接近实际编程实践的。

class SimpleTest {
    void met( Object a ) {
        println "Object"
    }

    void met( String b ) {
        println "String"
    }

    static main( args ) {
        SimpleTest i = new SimpleTest()
        i.met(null)
    }
}

This code will produce the output "Object". It will not choose the most specialized version of the method. In this case String is more specialized than Object, so this rule does not apply.

解决方案

Groovy uses a distance calculation approach. Basically if you imagine the classes and interfaces as nodes in a graph and them being connected by their inheritance relationship, then we kind of look for the distance from our given argument type (the runtime type of the argument) to our parameter type (the static type the method parameter has). The connections have different weights, basically going to the super class means a distance of I think 3, to an interface 1, wrapping a primitive is also 1, vargs wrapping has also a weight (and cannot really be represented in the graph anymore, so sorry for the slightly failing image)

In case of null this cannot work of course. Here we look at the distance of the parameter type to Object instead. While the none-null case is the most possible special method we take for the null part the most general one instead. In Java you would normally have the static type or use a cast to ensure what is to be selected. In Groovy we don't have a static type and what is most special can often not be decided correctly. Thus we decided for the most general approach instead for that case. It works really well in general.

Object then is kind of like a fallback, that allows you central null handling. In future versions we may allow the usage of an explicit null type, which then would be preferred over Object if there.

While you can often see directly the distance approach for classes, it is a bit more complicated for interfaces. Basically the algorithm goes like this: If my current class directly implements the interface we are looking for, then it is a match with distance 1. If any of the interfaces the class implements has the interface we look for as parent, then count the "hops" till we are there as distance. But we look for the shortest distance. So we also look the same way at the super class. Any search result from there will have that distance +1 (for the super class hop). If the super class search gives a shorter distance than the search on the implementing interfaces, the super class search result will be taken instead.

As for handling null with interfaces... The distance to Object is here 1 if the interface does not extend another. If it does it is the distance of the parent interface +1. If multiple interfaces are extended, it is the shortest path again.

Let us look at List and Integer for null.
List extends Collection, Collection extend Iterable, Iterable has no parent. That makes a distance of 1 for Iterable, 2 for Collection and finally 3 for List. Integer extends Number, Number extends Object. Since we hop two times we have a distance of 6 here (2x3), being much bigger than the other case. Yes, that means in general we prefer interfaces. We do that for practical reasons actually, since this way proofed to be most near actual programming practice.

这篇关于当null作为参数传递时,Groovy选择了哪种重载方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆