如何在我的库中处理任意用户提供的类型?

时间:2013-08-10 12:40:53

标签: java generics shared-libraries

我正在编写一个能够处理六边形网格的库。

用户可以访问HexagonGridBuilder对象,在该对象中,他可以为网格设置宽度,高度和许多其他参数,并且其build()方法返回HexagonGrid对象。 HexagonGrid有各种方法来获取Hexagon(例如通过网格坐标或像素坐标)。

我的问题是我希望允许用户在Hexagon上的每个HexagonGrid对象中放置任意卫星数据。这样做的最佳做法是什么?

我可以提供通用方法,允许用户将卫星数据传递到Hexagon

private Object satelliteData;

public <T> void setSatelliteData(T satelliteData) {
    this.satelliteData = satelliteData;
}

@SuppressWarnings("unchecked")
public <T> T getSatelliteData() {
    return (T) satelliteData;
}

这显然是有缺陷的,因为它涉及铸造物体而不确定它们的类型是什么。

我可以修改我的HexagonGridBuilder,以便用户可以为其卫星数据传递Class对象,以便我可以验证他是否提供了正确的类型:

   public <T> void setSatelliteData(T satelliteData) {
    if (!satelliteClass.isAssignableFrom(satelliteData.getClass())) {
        // throw some exception
    }
    this.satelliteData = satelliteData;
}

但是这仍然会涉及getSatelliteData()方法中未经检查的强制转型:

@SuppressWarnings("unchecked")
public <T> T getSatelliteData() {
    return (T) satelliteData;
}'

正确的搜索似乎使整个库具有通用性,因此我有一个卫星数据类型的通用参数,但它涉及使每个类都涉及通用:

HexagonGrid<SATELLITE_DATA_TYPE> hexagonGrid =
new HexagonGridBuilder<SATELLITE_DATA_TYPE>().build();

所以我不确定选择哪一个。哪个是最不讨厌的解决方案?或者还有其他我没想过的东西?

编辑:我真正希望知道的是,让我所涉及的所有类都变得通用(这将使它们更难理解并且有点混乱)或者我可以在我的构建器中使用2个泛型方法和一个plus方法来提供类吗?原因是用户可能不会使用任何卫星数据,因此会大惊小怪。

1 个答案:

答案 0 :(得分:3)

您需要将<T>作为类型参数放在整个HexagonGrid类上,而不仅仅放在方法上。然后,您可以将字段定义为private T satelliteData,消除方法上的<T>,并删除显式转换。这基本上就是你上次谈到的方法。

如果您有理由使用构建器而不是构造函数,则不一定要对构建器进行泛化;您可以将type参数传递给build方法。有关其外观的示例,请参阅EnumSet#noneOf

(另外,考虑到您的其他要求,您可能需要查看制作类型参数<T extends Satellite>,或任何基本卫星接口。)