我可以使它工作吗?

(我使用Eclipse Luna 4.4.0,JDK 1.8.0_05)

我正在做一个游戏,游戏世界的拓扑可以大致分解为World -> Level -> Tile ,其中平铺是一个小单元的地形。 我建立了三个项目,一个为这些结构保存一些基类,另外两个是服务器和客户端,它们扩展了基础项目中的结构,以满足每个项目所需的额外事项。 像这样:

基地项目:

public class BaseWorld{/* ...code... */}
public class BaseLevel{/* ...code... */}
public class BaseTile{/* ...code... */}

在服务器和客户端项目中:

public class World extends BaseWorld{/* ...extended code... */}
public class Level extends BaseLevel{/* ...extended code... */}
public class Tile extends BaseTile{/* ...extended code... */}

现在基础项目的很多部分都有返回基类的方法,但在服务器和客户端项目中,这通常意味着我必须重写方法并转换为子类型,因为子项目专门使用子类型。 像这样:

public class BaseLevel{
  BaseLevel getNextLevel(){/* ...code... */}
}

public class Level extends BaseLevel{
  Level getNextLevel(){
    return (Level)super.getNextLevel();
  }
}

这是一个很难保持的状态。 我发现我可以使用泛型来解决其中的一些问题,具体如下:

public class BaseLevel<Level extends BaseLevel<Level>>{
  Level getNextLevel(){/* ...code... */}
}

public class Level extends BaseLevel<Level>{
  //All sorted! getNextLevel() already returns this subclass type.
}

好吧,我有这个疯狂的想法,将上述模式转化为切入点,并能够在所有超类中的所有子类中使用。 现在我必须说,我绝不认可下面的代码是很好的编程,我只是想出了一些想法,并尽我所能去看看它是如何工作的。 无论如何,我想出了以下的怪物。

public class BaseWorld<Tile extends BaseTile<Tile, Level, World>
                      ,Level extends BaseLevel<Tile, Level, World>
                      ,World extends BaseWorld<Tile, Level, World>>{
  /* ...code... */
}

public class BaseLevel<Tile extends BaseTile<Tile, Level, World>
                      ,Level extends BaseLevel<Tile, Level, World>
                      ,World extends BaseWorld<Tile, Level, World>>{
  /* ...code... */
}

public class BaseTile<Tile extends BaseTile<Tile, Level, World>
                 ,Level extends BaseLevel<Tile, Level, World>
                 ,World extends BaseWorld<Tile, Level, World>>{
  /* ...code... */
}

现在,无论何时我需要从任何其他类中返回任何类,我都可以不必在子项目中使用任何模型!

很不幸的是,因为当Eclipse重建工作区时:

A stack overflow error has occurred.
You are recommended to exit the workbench. [...]

我想,因为一个类的泛型正在得到解决,它必须去解决其他类的泛型,然后陷入递归循环。

提问时间:

这个错误的Eclipse编辑器有中风,还是java编译器?

上述内容在编辑器中不会突出显示为编译器警告/错误 - 即使它看起来在技术上有效吗?

这种递归可能是无限深的,还是非常深?

是否有可能在避免这个错误的同时达到我想要的效果? (我再次想强调,它绝对不是一个好模式,我只想知道它是否可以工作)


Eclipse编辑器是否有中风或java编译器?

在这种情况下,Eclipse编辑器。 下列声明(当然是在不同的文件中)是有效的Java代码。

public class BaseFoo<F extends BaseFoo<F,B>, B extends BaseBar<F,B>> {}
public class BaseBar<F extends BaseFoo<F,B> ,B extends BaseBar<F,B>> {}
public class Foo<F extends BaseFoo<F,B>,B extends BaseBar<F,B>> extends BaseFoo<F,B> {}
public class Bar<F extends BaseFoo<F,B>,B extends BaseBar<F,B>> extends BaseBar<F,B> {}

上述内容在编辑器中不会突出显示为编译器警告/错误 - 即使它看起来在技术上有效吗?

它可能应该(好吧,好吧,好吧,我在这里开玩笑......)不。这是有效的Java。 只是...呃...

这种递归可能是无限深的,还是非常深?

无限,我在这里猜测(更多关于我的猜测)。

考虑尝试实例化Foo一个实例。

继续,使用默认构造函数写出一个初始化程序。

Foo<Foo, Bar> foo = new Foo<Foo, Bar>();

这里有四个错误,关于泛型边界不匹配。

我们试图解决它。

Foo<Foo<Foo,Bar>, Bar<Foo,Bar>> foo = new Foo<Foo<Foo,Bar>, Bar<Foo,Bar>>();

现在有12个错误。 我们可以继续尝试初始化这个。

是否有可能在避免此错误的同时实现我在这里尝试的内容? (我再次想强调,它绝对不是一个好模式,我只想知道它是否可以工作)

考虑以下基本结构:

class World {
    SomeCollection<Level> levels;
}

class Level {
    SomeCollection<Tile> tiles;
}

class Tile { }

为什么?

前面代码的基本结构比继承更喜欢构造,除了某些内置泛型集合类型外,不使用泛型。 通过这个提供给你的初始化风格的一个很好的例子就是一个静态构建器,最终写出这样的东西来初始化一个World

World gameWorld = new World.Builder().
                 .loadLevels(levelSource)
                 .loadTiles(tileset)
                 .build();

我希望这有帮助。

结束笔记

不要继续。 这是探索解决您问题的途径。 不要再去这里。


多么奇妙的怪物!

您的代码在Eclipse 4.4.1和javac 1.8.0_45中编译得很好,并且看起来像是应该那样工作。 我认为他们在Java 8的早期版本中检查类型更加微妙的部分时遇到了一些问题; 也许他们现在已经整理出来了。

与jdphenix的观点相反,我认为这种设计可能有用。 我没有看到他的建议设计在静态类型控制和代码重用方面有什么优势。

例:

public class ElegantMonstrosity {
    public void m() {
        SubWorld world = new SubWorld();
        List<SubLevel> levels = world.getTiles(); 
        SubLevel level = levels.get(0);
        List<SubTile> tiles = level.getTiles();
        SubLevel nextLevel = level.getNextLevel();
    }
}

class BaseWorld<
    Tile extends BaseTile<Tile, Level, World>,
    Level extends BaseLevel<Tile, Level, World>,
    World extends BaseWorld<Tile, Level, World>> {

    List<Level> getTiles() { return null; }
}

class BaseLevel<
    Tile extends BaseTile<Tile, Level, World>,
    Level extends BaseLevel<Tile, Level, World>,
    World extends BaseWorld<Tile, Level, World>> {

    Level getNextLevel() { return null; }
    List<Tile> getTiles() { return null; }
}

class BaseTile<
    Tile extends BaseTile<Tile, Level, World>,
    Level extends BaseLevel<Tile, Level, World>,
    World extends BaseWorld<Tile, Level, World>> {
}

class SubTile extends BaseTile<SubTile, SubLevel, SubWorld> {}
class SubLevel extends BaseLevel<SubTile, SubLevel, SubWorld> {}
class SubWorld extends BaseWorld<SubTile, SubLevel, SubWorld> {}
链接地址: http://www.djcxy.com/p/80939.html

上一篇: can I make it work?

下一篇: Translating C preprocessor to Rust