M3 Java: 如何检查 class 是否从接口实现了一个函数
M3 Java: How to check that a class implements a function from an interface
我正在尝试编写一个分析来检查 class 是否实现了 Comparable.compareTo
|java+method:///java/lang/Comparable/compareTo(T)|.
我试过 M3.methodOverrides,在某些情况下它有效。但是对于下面的代码,methodOverrides 根本不包含 compareTo。
//Geometric.java
public interface Geometric extends Comparable<Geometric> {
public double area();
}
//Circle.java
public class Circle implements Geometric {
private double r;
private double x;
private double y;
public Circle(double x, double y, double r) {
this.x = x;
this.y = y;
this.r = r;
}
@Override
public double area() {
return Math.PI * Math.pow(r, 2);
}
@Override
public int compareTo(Geometric o) {
return (int) (area() - o.area());
}
@Override
public String toString() {
return "Circle...";
}
}
使用 createM3FromDirectory
加载这些文件时,M3.methodOverrides 仅包含一个条目:
<|java+method:///Circle/area()|,|java+method:///Geometric/area()|>
有没有办法对 M3 中的某些关系采取一些传递闭包来得出结论
|java+method:///Circle/compareTo(Geometric)|
覆盖 |java+method:///java/lang/Comparable/compareTo(T)|
?
目前,M3 仅存储与直接超类和接口相关的方法覆盖。如果在您的项目中声明了传递接口和超类型,您可以使用 implements
和 extends
关系的传递闭包,然后对照 declarations
和 [=13= 交叉检查结果] 关系。但是,您需要注意,在外部依赖项(例如 Comparable<T>
)的情况下,您的 M3 中不会包含所有需要的信息。因此,这不是解决所有情况的通用解决方法。如果您仍想检查项目实体的方法覆盖,请考虑以下步骤(这只是一种可能的解决方案):
- 计算
implements
关系的传递闭包。
- 计算
extends
关系的传递闭包。
- 根据您正在检查的类型订阅这两个关系并聚合这两个集合(即
transImpl[|java+class://main/MyClass|] + transExt[|java+class://main/MyClass|]
)。
- 考虑
containment
关系中与 MyClass
类型及其传递父类型相关的方法。
- 将
MyClass
方法的签名与传递父类型方法进行比较(注意每个方法的可见性;仅应考虑 protected
和 public
方法)。
无论如何,我们在 Rascal 存储库中打开了一个新的 issue 以进一步分析您的查询。感谢您报告。
我简直不敢相信自己的眼睛。我刚刚又试了一次,现在可以了。
//Main.rsc
module Main
import IO;
import lang::java::m3::Core;
void main(list[str] args)
{
loc projectDir = |file:///| + args[0];
M3 model = createM3FromDirectory(projectDir);
for( ov <- model.methodOverrides ) { println(ov); }
}
eclipse rascal 控制台内部:
rascal>main(["/home/mkl/radboud/src/java-feedback/java-feedback-rascal/test-data/assignment03-override-not-detected"]);
Reloading module Main
<|java+method:///Circle/toString()|,|java+method:///java/lang/Object/toString()|>
<|java+method:///Circle/area()|,|java+method:///Geometric/area()|>
<|java+method:///Circle/compareTo(Geometric)|,|java+method:///java/lang/Comparable/compareTo(T)|>
就是这样:Circle 实际上实现了 Comparable.compareTo。
<|java+method:///Circle/compareTo(Geometric)|,|java+method:///java/lang/Comparable/compareTo(T)|>
我认为问题在于我使用了两个不同版本的 rascal。 Rascal shell,似乎是旧版本,给出不同的结果。
使用流氓-shell:
$ java -Xmx1G -Xss32m -jar ~/tmp/rascal-shell-stable.jar Main.rsc /home/mkl/radboud/src/java-feedback/java-feedback-rascal/test-data/assignment03-override-not-detected
Version: unknown
<|java+method:///Circle/area()|,|java+method:///Geometric/area()|>
我想我只是运行流氓-shell。当 运行 来自 eclipse 内部时,它会给出正确的结果。
就我而言,它按预期工作。
P.S。我明白M3只记录即时事实,需要时我必须自己计算传递闭包。
我正在尝试编写一个分析来检查 class 是否实现了 Comparable.compareTo
|java+method:///java/lang/Comparable/compareTo(T)|.
我试过 M3.methodOverrides,在某些情况下它有效。但是对于下面的代码,methodOverrides 根本不包含 compareTo。
//Geometric.java
public interface Geometric extends Comparable<Geometric> {
public double area();
}
//Circle.java
public class Circle implements Geometric {
private double r;
private double x;
private double y;
public Circle(double x, double y, double r) {
this.x = x;
this.y = y;
this.r = r;
}
@Override
public double area() {
return Math.PI * Math.pow(r, 2);
}
@Override
public int compareTo(Geometric o) {
return (int) (area() - o.area());
}
@Override
public String toString() {
return "Circle...";
}
}
使用 createM3FromDirectory
加载这些文件时,M3.methodOverrides 仅包含一个条目:
<|java+method:///Circle/area()|,|java+method:///Geometric/area()|>
有没有办法对 M3 中的某些关系采取一些传递闭包来得出结论
|java+method:///Circle/compareTo(Geometric)|
覆盖 |java+method:///java/lang/Comparable/compareTo(T)|
?
目前,M3 仅存储与直接超类和接口相关的方法覆盖。如果在您的项目中声明了传递接口和超类型,您可以使用 implements
和 extends
关系的传递闭包,然后对照 declarations
和 [=13= 交叉检查结果] 关系。但是,您需要注意,在外部依赖项(例如 Comparable<T>
)的情况下,您的 M3 中不会包含所有需要的信息。因此,这不是解决所有情况的通用解决方法。如果您仍想检查项目实体的方法覆盖,请考虑以下步骤(这只是一种可能的解决方案):
- 计算
implements
关系的传递闭包。 - 计算
extends
关系的传递闭包。 - 根据您正在检查的类型订阅这两个关系并聚合这两个集合(即
transImpl[|java+class://main/MyClass|] + transExt[|java+class://main/MyClass|]
)。 - 考虑
containment
关系中与MyClass
类型及其传递父类型相关的方法。 - 将
MyClass
方法的签名与传递父类型方法进行比较(注意每个方法的可见性;仅应考虑protected
和public
方法)。
无论如何,我们在 Rascal 存储库中打开了一个新的 issue 以进一步分析您的查询。感谢您报告。
我简直不敢相信自己的眼睛。我刚刚又试了一次,现在可以了。
//Main.rsc
module Main
import IO;
import lang::java::m3::Core;
void main(list[str] args)
{
loc projectDir = |file:///| + args[0];
M3 model = createM3FromDirectory(projectDir);
for( ov <- model.methodOverrides ) { println(ov); }
}
eclipse rascal 控制台内部:
rascal>main(["/home/mkl/radboud/src/java-feedback/java-feedback-rascal/test-data/assignment03-override-not-detected"]);
Reloading module Main
<|java+method:///Circle/toString()|,|java+method:///java/lang/Object/toString()|>
<|java+method:///Circle/area()|,|java+method:///Geometric/area()|>
<|java+method:///Circle/compareTo(Geometric)|,|java+method:///java/lang/Comparable/compareTo(T)|>
就是这样:Circle 实际上实现了 Comparable.compareTo。
<|java+method:///Circle/compareTo(Geometric)|,|java+method:///java/lang/Comparable/compareTo(T)|>
我认为问题在于我使用了两个不同版本的 rascal。 Rascal shell,似乎是旧版本,给出不同的结果。
使用流氓-shell:
$ java -Xmx1G -Xss32m -jar ~/tmp/rascal-shell-stable.jar Main.rsc /home/mkl/radboud/src/java-feedback/java-feedback-rascal/test-data/assignment03-override-not-detected
Version: unknown
<|java+method:///Circle/area()|,|java+method:///Geometric/area()|>
我想我只是运行流氓-shell。当 运行 来自 eclipse 内部时,它会给出正确的结果。
就我而言,它按预期工作。
P.S。我明白M3只记录即时事实,需要时我必须自己计算传递闭包。