Cal*_*lid 4 groovy multiple-inheritance typechecking
@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
}
}
Run Code Online (Sandbox Code Playgroud)
从本质上讲,有没有办法实现这一点,而不会牺牲以下三个属性轮廓中的任何一个main():
我不认为你可以用课程做到这一点.也许你想要的特性(在讨论 更新中: 在Groovy 2.3中可用并且已经摇摆不定!),或者,对于纯动态解决方案,@Mixin你需要备份一个好的测试套件.
我的猜测:这@Delegate是你最好的朋友,但是,就目前而言,你只能将一个Chest对象存储在一个Container类型变量中.所以你需要一些接口.
即使超类不在您的控制之下,您也可以使用groovy as运算符来实现接口.
首先,我重写了你的类以删除abstract和添加接口:
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[]
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我没有添加HasContent到Location,展现的使用as.
第二,来了Container和Chest.@Delegate添加并自动继承委托的接口:
@TC
abstract class Container {
@Delegate Location location = new Location()
@Delegate Entity entity = new Entity()
}
@TC class Chest extends Container { }
Run Code Online (Sandbox Code Playgroud)
最后,只要您坚持使用接口,它就可以进行类型检查:
@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]
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3743 次 |
| 最近记录: |