1

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

用户可以访问一个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 方法在我的构建器中提供类?原因是用户可能不会使用任何卫星数据,因此会大惊小怪。

4

1 回答 1

3

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

如果你想使用构建器而不是构造器是有原因的,那么你不一定要对构建器进行泛化;您可以将类型参数传递给该build方法。请参阅EnumSet#noneOf以了解其外观示例。

(此外,考虑到您的其他要求,您可能需要考虑制作类型参数<T extends Satellite>,或者您的基本卫星接口是什么。)

于 2013-08-10T12:52:51.167 回答