@groovy.transform.TypeChecked abstract class Entity { ... double getMass() { ... } ... } @groovy.transform.TypeChecked abstract class Location { ... Entity[] getContent() { ... } ... } @groovy.transform.TypeChecked abstract class Container {...} //inherits,somehow,from both Location and Entity @groovy.transform.TypeChecked class Main { void main() { double x Container c = new Chest() //Chest extends Container Entity e = c x = e.mass Location l = c x = l.content //Programmer error,should throw compile-time error } }
从本质上讲,有没有办法实现这一点,而不会牺牲main()中的三个属性轮廓中的任何一个:
>直接访问字段,甚至虚拟字段
>分配给两个超类
> Typechecking(编译时)
解决方法
我不认为你可以用课程做到这一点.也许你想要
traits(在讨论更新:
available in Groovy 2.3并且已经摇摆不定!)或者,对于一个纯粹的动态解决方案,@ Mixin,你需要备份一个好的测试套件.
我猜:@Delegate是你最好的朋友,但是,就目前而言,你只能将一个Chest对象存储在Container类型变量中.所以你需要一些接口.
即使超类不在您的控制之下,您也可以使用groovy作为运算符来实现接口.
import groovy.transform.TypeChecked as TC interface HasMass { double mass } interface HasContent { Entity[] getContent() } @TC class Entity implements HasMass { double mass } @TC class Location { Entity[] getContent() { [new Entity(mass: 10.0),new Entity(mass: 20.0)] as Entity[] } }
注意我没有将HasContent添加到Location,以显示as的用法.
第二,来到集装箱和箱子.添加@Delegate并自动继承委托的接口:
@TC abstract class Container { @Delegate Location location = new Location() @Delegate Entity entity = new Entity() } @TC class Chest extends Container { }
最后,只要您坚持使用接口,它就可以进行类型检查:
@TC class Mult { static main(args) { def x // use 'def' for flow-typing Container c = new Chest() //Chest extends Container HasMass e = c x = e.mass def l = c as HasContent x = l.content //Programmer error,should throw compile-time error assert c.content.collect { Entity it -> it.mass } == [10.0,20.0] } }