在这种情况下,为什么我需要演员?

时间:2016-02-05 00:02:22

标签: java extends

示例:

RewriteRule ^birthing-records/([^/]+)/?$ birthing-records.php?url=$1 [QSA,NC]
RewriteRule ^birthing-records/([^/]+)/([^/]+)/?$ birthing-records.php?url=$1&second=$2 [L,QSA,NC]

由于我的CityEntity属于AbstractEntity类型,为什么我不能在cityconverter中这样做?

class AbstractConverter <T> {
   public abstract T convert(AbstractEntity e);
} 

class CityEntity extends AbstractEntity {...}

class CityConverter extends AbstractConverter {
  @Override
  public CityDTO convert(CityEntity entity) {...} // why can't I do that??
}

我想解决方案就是投射,但它不是优雅的:

  The method convert(CityEntity) of type CityConverter must override or implement a supertype method

2 个答案:

答案 0 :(得分:3)

您无法减少允许的参数类型,因为您会中断Liskov substitution principle。如果在未知的convert实施中调用AbstractConverter(由于多态),他会猜测他总是可以通过任何AbstractEntity实现。如果CityConverter仅允许非常特定的子类型,则情况并非如此。

现在关于你的代码:

class AbstractConverter <T> {
   public abstract T convert(AbstractEntity e);
}

这里首先让我感到惊讶的是:为什么AbstractEntity是固定类型?如果我总是想将AbstractEntityConverter实例转换为不同的实例,我会将转换器类命名为AbstractEntity或类似的东西。

所以我想你真的想要这样的东西:

class AbstractConverter<F, T> {
   public abstract T convert(F source);
}

F是&#34;来自&#34;作为源的类型,T是目标类型,将返回。因此,您可以让AbstractConverter子类型决定他们想要转换的内容。

然后你有这个:

class CityConverter extends AbstractConverter {
}

为什么在这里使用AbstractConverter作为raw type?不应该吗?

class CityConverter extends AbstractConverter<CityDTO> {
}

但无论如何,如果您想使用我的建议,那么还要添加源类型:

class CityConverter extends AbstractConverter<CityEntity, CityDTO> {
    @Override
    public CityDTO convert(CityEntity entity) {...}
}

这样可行。

答案 1 :(得分:2)

您的CityConverter extends AbstractConverterAbstractConverter<T>需要实施

public abstract T convert(AbstractEntity e);

extends AbstractConverter使用原始类型不是问题,因为在返回对象的情况下,重写方法可以更具体(因为它仍然是父类描述的类型)。

但是在派生类中你想要更具体的类型作为参数时会出现问题。

请记住派生类仍然可以在父类型之一的引用中使用,就像它可以有如下代码:

AbstractConverter ac = new CityConverter();

因此,当我们调用ac.convert(...)时,编译器将允许我们使用任何类型的AbstractEntity作为参数,而不仅仅CityEntity可以制作CityConverter#convert的代码。

这就是为什么我们在覆盖它时不能声明更具体类型的方法参数。

现在关于你的标题问题:

  

在这种情况下,为什么我需要演员?   ......

CityEntity cityEntity = (CityEntity) entity;

您需要进行转换,因为entity被声明为AbstractEntity,这意味着传递的实例可能不是CityEntity类型,因此编译器无法编译代码:

CityEntity cityEntity = entity;//error without cast

通过投射,你基本上是在说#34;我确信传递的实例将是(CityEntity)类型,如果没有,我愿意面对后果,并准备好看看我的应用程序被ClassCastException和#34停止了;