这个复杂的泛型模式崩溃Eclipse - 我可以让它工作吗? [英] This convoluted generics pattern crashes Eclipse - can I make it work?

查看:126
本文介绍了这个复杂的泛型模式崩溃Eclipse - 我可以让它工作吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



我在制作游戏,游戏世界的拓扑结构大致细分为 World - >级别 - >平铺,其中平铺是一个小单位的地形。我有三个项目设置,一个保存这些结构的一些基类,另外两个是服务器和客户端,扩展基础项目中的结构,每个项目所需的额外的东西。像这样:



基本项目:

  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> {
//全部排序! getNextLevel()已经返回这个子类型。
}

我有这个疯狂的想法,将上述模式弯曲到断点,能够在所有超类中使用所有的子类。现在我必须说,我绝对不支持下面的代码作为好的编程,我只是有了这个想法,并把它尽可能只是为了看看它将如何工作。无论如何,我想出了以下的怪异。

  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扩展BaseTile< Tile,Level,World>
,Level extends BaseLevel< Tile,Level,World>
,World extends BaseWorld< Tile,Level,World>> {
/ * ... code ... * /
}

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

现在,每当我需要从任何其他类返回任何类,我可以不必在子项目中使用任何投射!



很遗憾没有,因为当Eclipse重建工作区时:

 错误已发生。 
建议您退出工作台。 [...]



我想一个类的泛型正在解决,并解析其他类的泛型,然后在递归循环中捕获。



问题时间



这个错误是Eclipse编辑器有一个笔划还是java编译器?



上面的代码在编辑器中没有突出显示为编译器警告/



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



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

解决方案

Eclipse编辑器是否有笔触或Java编译器?



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

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

上述编辑器中没有突出显示为编译器警告/错误 - 即使它似乎在技术上是有效的吗?



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



这次递归可能是无限深,还是非常深? b
$ b

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



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



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

  Foo   

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



让我们尝试解决它。

  Foo< Foo< Foo,Bar>,Bar< Foo,Bar> foo = new Foo< Foo< Foo,Bar>,Bar< Foo,Bar> 

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



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



考虑以下基本结构:

  class World {
SomeCollection< Level&水平;
}

class Level {
SomeCollection< Tile>瓷砖;
}

class Tile {}



上述代码的基本结构优先于 composition over inheritance ,除了在一些内置的通用集合类型中不使用泛型。这个初始化风格的一个很好的例子是静态构建器,最终写成这样来初始化世界

 世界游戏世界= new World.Builder()。 
.loadLevels(levelSource)
.loadTiles(tileset)
.build();

我希望这有帮助。



结束注释



不要继续。这是一个可能的解决您的问题的路径。不要再去这里。


(I'm using Eclipse Luna 4.4.0, JDK 1.8.0_05)

I'm making a game, and the topology of the game world can be roughly broken down into World -> Level -> Tile, where a Tile is a a small unit of terrain. I have three projects set up, one which holds some base classes for those structures, and the other two are server and client which extend the structures in the base project for the additional things that each of those projects need. Like so:

Base project:

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

In both server and client projects:

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

Now in many parts of the base project, there are methods which return the base classes, but in the server and client projects this typically means I have to override the methods and cast to the sub-type, because the sub projects exclusively using the sub types. Like so:

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

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

And that's sort of a pain to maintain. I discovered that I can use generics to solve some of this, with the following pattern:

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

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

Well I had this crazy idea to bend the above pattern to breaking point and be able to use all the subclasses everywhere in the all the superclasses. Now I must say that I in no way endorse the following code as good programming, I just had the idea and took it as far as I could just to see how it would work out. Anyway, I came up with the following monstrosity.

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... */
}

Now, whenever I need to return any of the classes from any other, I can without having to use any casting whatsoever in the sub-projects!

Well unfortunately not, because when Eclipse rebuilds the workspace:

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

I guess as the generics of one class are being resolved, it has to go and resolve the generics of the other class and then gets caught in a recursive loop.

Question time:

Is this error Eclipse editor having a stroke, or the java compiler?

The above doesn't highlight in the editor as a compiler warning/error - should it, even though it seems technically valid?

Is it likely that this recursion is infinitely deep, or just very deep?

Is it possible to achieve what I'm trying to here while avoiding this error? (I once again want to emphasize that its definitely not a good pattern, I just want to know if it can work)

解决方案

Is the Eclipse editor having a stroke, or the java compiler?

The Eclipse editor in this case. The following declarations together (in different files, of course), are valid Java code.

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> {}

The above doesn't highlight in the editor as a compiler warning/error - should it, even though it seems technically valid?

It probably should (okay, okay, fine, I joke here...) No. This is valid Java. Just... eh...

Is it likely that this recursion is infinitely deep, or just very deep?

Infinite, and I'm guessing here (more on my guess in a moment).

Consider attempting to instantiate an instance of Foo.

Go ahead, write out an initializer using the default constructor.

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

There are four errors here, regarding the generic bounds mismatch.

Let's attempt to resolve it.

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

Now there's 12 errors. We could go on forever trying to initialize this.

Is it possible to achieve what I'm trying to here while avoiding this error? (I once again want to emphasize that its definitely not a good pattern, I just want to know if it can work)

Consider the following basic structure:

class World {
    SomeCollection<Level> levels;
}

class Level {
    SomeCollection<Tile> tiles;
}

class Tile { }

Why?

The basic structure of the preceding code is preferring composition over inheritance, and doesn't use generics except in some built-in generic collection type. One nice example of an initialization style afforded to you by this is a static builder, ending up writing something like this to initialize a World:

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

I hope this helps.

Closing notes

Do not proceed. This is an explored path for a possible solution to your problem. Don't go here again.

这篇关于这个复杂的泛型模式崩溃Eclipse - 我可以让它工作吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆