groovy 的扩展模块特性是 java 继承特性的混合形式吗?为什么扩展模块需要声明为静态?
3 回答
不幸的是,参考文档和其他文档没有定义扩展方法的语义:
- 问:他们可以覆盖实例方法吗?我通过Category 方法和expando 方法
测试了扩展方法。两种方法都不会覆盖实例方法。我没有测试通过模块描述符安装的扩展模块。use
metaClass
- 问:它们可以被子类的扩展方法覆盖吗?
我也测试过。use
方法和metaClass
扩展方法不会被子类的扩展方法覆盖。 - 问:他们可以调用继承的
super
方法吗?
不,因为它们是通过static
方法实现的。 - 问:他们可以调用私有方法吗?
实验表明他们可以,令人惊讶的是。 - 问:他们可以访问私有实例变量吗?
不,因为它们是通过static
方法实现的。 - 问:它们可以从 Java 方法调用吗?
也许,如果扩展模块在编译调用代码时位于类路径上。我没有测试它。
结论: 扩展方法不是继承的一种形式。它们似乎是通用函数调用语法 (UFCS)的动态形式,也就是说,当语言找不到方法variable.foo(arguments)
时,它会寻找要调用的静态扩展函数foo(variable, arguments)
。[如果错误,请纠正我的假设!]
您问为什么将它们定义为static
. 这似乎符合语义:一个不涉及继承的静态函数,尽管它的调用语法使它看起来像一个方便的方法调用。
您可以使用@groovy.lang.Category注解来编写类似实例方法的扩展方法。这会在编译时进行 AST 转换,以将其转换为合适的静态方法。
另请参阅Groovy 特征。那是(mixin)继承的一种形式。
简短的回答是我认为是的。很难清楚地回答,因为扩展方法的继承完全由运行时(和静态编译器)完成。因此,它与 Java 如何进行继承无关。
回答第二个问题......它们是静态的,因为对于需要状态的情况,您通常使用元类。扩展方法最初被认为是方便方法或使 API 更 Groovy。因此,它们是添加到元类中的一种特殊形式的方法。您可以将它们视为简化版本。但这也意味着他们没有所有的能力。实现扩展方法,可以在每个“自我”对象的基础上保持本地状态(基本上是字段/属性会做什么)实际上很难做到高效......但是您始终可以为此使用每个实例元类。
出于所有广泛的目的,它们是语法糖,因此静态方法看起来更像 OOP。没有继承是因为 Java 和 Groovy 中的静态方法不参与继承(即类不继承静态方法)。
这些方法需要是静态的,因为编译器不知道如何实例化扩展方法的周围类。
但是我相信有些语言确实允许在封闭类之外定义方法并进行某种继承,但不是很多(我相信 CLOS 和 Dylan 会这样做)。此外,它们还有许多似乎允许添加方法的语言,但“对象”的类型实际上已更改/隐藏为其他类型。这被称为临时多态(例如 Clojure、Haskell、Golang 和 Scala),但又与包含多态(Java 继承)无关。