方法链接 + 继承 2 次或更多次
Method chaining + inheritance 2 or more times
我不希望能够方法链多个向量 class 构建在彼此之上。我希望能够扩展 class.
这是二维的:
public class Vec2 < C extends Vec2 > {
public double x, y;
public Vec2() {
}
public Vec2(double x, double y) {
this.x = x;
this.y = y;
}
public C add(double x, double y) {
this.x += x;
this.y += y;
return (C) this;
}
}
这是一个带有 z 元素的向量。
class Vec3 < C extends Vec3 > extends Vec2<Vec3> {
double z;
public Vec3(){}
public Vec3(double x, double y, double z) {
super(x, y);
this.z = z;
}
public C add(double x, double y, double z) {
super.add(x, y);
this.z += z;
return (C) this;
}
}
但是当我使用 Vec3 时,一旦我连续两次使用 Vec2 中的方法,它就会 returns 一个 Vec2。
Vec3<Vec3> a = new Vec3<>();
// ------------------------------------------------->.add() in Vec2 cannot be aplied
a.add(10, 20).add(10, 20, 10).add(10, 20).add(10, 20).add(10, 10, 20);
我不想这样写 class:
class Vec3 extends Vec2<Vec3> {
// constructor etc. like before...
public Vec3 add(double x, double y, double z) {
super.add(x, y);
this.z += z;
return this;
}
}
因为当我制作一个 Vec4 时,我必须覆盖 Vec3 中的每个方法。
有没有办法(语法)解决这个问题?无论在哪里 它一直返回正确的 class.
问题是您的定义中有很多 "raw" 类型,例如
Vec2 < C extends Vec2 >
----
raw type!
几轮之后,你会得到原始类型,erasure 使 C
与 Vec2
相同。
我们可以执行以下操作,使用类型变量 This
作为 "self type"
public class Vec2<This> {
public This add(double x, double y) {
this.x += x;
this.y += y;
return (This) this;
}
}
public class Vec3<This> extends Vec2<This> {
public This add(double x, double y, double z) {
super.add(x, y);
this.z += z;
return (This) this;
}
}
public class Vec4<This> extends Vec3<This> {
etc.
但等一下,我们如何向 Vec3
提供 This
?
Vec3<Vec3<Vec3<......>>> ???
我们可以使用助手class
public class V3 extends Vec3<V3>{}
现在一切正常; V3
return V3
中的所有 add()
方法
V3 a = new V3();
a.add(10, 20).add(10, 20, 10).add(10, 20).add(10, 20).add(10, 10, 20);
您无法完全按照您的意图实现您的代码,但我相信以下编译可以捕捉您的意图:
interface Vec<C extends Vec<C>> {
C add(C c);
}
class Vec2 implements Vec<Vec2> {
public double x, y;
public Vec2() {
}
public Vec2(double x, double y) {
this.x = x;
this.y = y;
}
public Vec2 add(Vec2 c) {
this.x += c.x;
this.y += c.y;
return this;
}
}
static class Vec3 implements Vec<Vec3> {
Vec2 vec2;
double z;
public Vec3() {
this(0,0,0);
}
public Vec3(double x, double y, double z) {
vec2 = new Vec2(x, y);
this.z = z;
}
public Vec3 add(Vec3 c) {
vec2.add(new Vec2(c.vec2.x, c.vec2.y));
this.z += z;
return this;
}
}
我不希望能够方法链多个向量 class 构建在彼此之上。我希望能够扩展 class.
这是二维的:
public class Vec2 < C extends Vec2 > {
public double x, y;
public Vec2() {
}
public Vec2(double x, double y) {
this.x = x;
this.y = y;
}
public C add(double x, double y) {
this.x += x;
this.y += y;
return (C) this;
}
}
这是一个带有 z 元素的向量。
class Vec3 < C extends Vec3 > extends Vec2<Vec3> {
double z;
public Vec3(){}
public Vec3(double x, double y, double z) {
super(x, y);
this.z = z;
}
public C add(double x, double y, double z) {
super.add(x, y);
this.z += z;
return (C) this;
}
}
但是当我使用 Vec3 时,一旦我连续两次使用 Vec2 中的方法,它就会 returns 一个 Vec2。
Vec3<Vec3> a = new Vec3<>();
// ------------------------------------------------->.add() in Vec2 cannot be aplied
a.add(10, 20).add(10, 20, 10).add(10, 20).add(10, 20).add(10, 10, 20);
我不想这样写 class:
class Vec3 extends Vec2<Vec3> {
// constructor etc. like before...
public Vec3 add(double x, double y, double z) {
super.add(x, y);
this.z += z;
return this;
}
}
因为当我制作一个 Vec4 时,我必须覆盖 Vec3 中的每个方法。
有没有办法(语法)解决这个问题?无论在哪里 它一直返回正确的 class.
问题是您的定义中有很多 "raw" 类型,例如
Vec2 < C extends Vec2 >
----
raw type!
几轮之后,你会得到原始类型,erasure 使 C
与 Vec2
相同。
我们可以执行以下操作,使用类型变量 This
作为 "self type"
public class Vec2<This> {
public This add(double x, double y) {
this.x += x;
this.y += y;
return (This) this;
}
}
public class Vec3<This> extends Vec2<This> {
public This add(double x, double y, double z) {
super.add(x, y);
this.z += z;
return (This) this;
}
}
public class Vec4<This> extends Vec3<This> {
etc.
但等一下,我们如何向 Vec3
提供 This
?
Vec3<Vec3<Vec3<......>>> ???
我们可以使用助手class
public class V3 extends Vec3<V3>{}
现在一切正常; V3
return V3
add()
方法
V3 a = new V3();
a.add(10, 20).add(10, 20, 10).add(10, 20).add(10, 20).add(10, 10, 20);
您无法完全按照您的意图实现您的代码,但我相信以下编译可以捕捉您的意图:
interface Vec<C extends Vec<C>> {
C add(C c);
}
class Vec2 implements Vec<Vec2> {
public double x, y;
public Vec2() {
}
public Vec2(double x, double y) {
this.x = x;
this.y = y;
}
public Vec2 add(Vec2 c) {
this.x += c.x;
this.y += c.y;
return this;
}
}
static class Vec3 implements Vec<Vec3> {
Vec2 vec2;
double z;
public Vec3() {
this(0,0,0);
}
public Vec3(double x, double y, double z) {
vec2 = new Vec2(x, y);
this.z = z;
}
public Vec3 add(Vec3 c) {
vec2.add(new Vec2(c.vec2.x, c.vec2.y));
this.z += z;
return this;
}
}