繁体   English   中英

在Java中使用通用子类型对象创建通用工厂

[英]Create generic factory with generic subtype object in Java

我已经用Java编写了一个转换器结构 ,我想为此创建一个工厂。

我的基本想法是,我传入一个有效类型的类并接收一个有效的子类型转换器,但是在泛型和继承部分失败。

这是我的界面:

interface ItemRequestConverterFactory {

  public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> clazz);

}

和实现:

public class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory {

  @Override
  public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> clazz) {
    if (clazz.equals(CreatePartRequestConverter.class))
    return new CreatePartRequestConverter();

    return null;
  }

}

不幸的是,Eclipse说:“类型不匹配:无法从CreatePartRequestConverter转换为ItemRequestConverter”。

我的通用签名中的问题出在哪里?

您似乎在类型参数和它们实际应该表示的类型之间不匹配:您正在将Class<IR>传递给newInstance方法。 这是一个表示ItemRequest的类。 但是,您正在将该类实例与可能是ItemRequestConverter接口的实现的类进行比较。

尽管在将适当的类型参数添加到CreatePartRequestConverter类时会编译,但这可能不是您想要实现的:

interface ItemRequestConverter<IR extends ItemRequest>{}
interface ItemRequest{}
interface ItemRequestConverterFactory 
{
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> itemRequestClass);
}
class CreatePartRequestConverter<IR extends ItemRequest> implements ItemRequestConverter<IR>
{
}

class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory 
{

    @Override
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(Class<IR> itemRequestClass) 
    {
        // Does not make sense: Comparing ItemRequest class with something
        // that is probably an implementation of ItemRequestConverter
        if (itemRequestClass.equals(CreatePartRequestConverter.class))
        {
            return new CreatePartRequestConverter<IR>();
        }
        return null;
    }
}

根据您实际想要实现的目标,可以将ItemRequestConverter类传递给工厂方法(并相应地对方法进行参数化):

interface ItemRequestConverter<IR extends ItemRequest>{}
interface ItemRequest{}
interface ItemRequestConverterFactory 
{
    public <IRC extends ItemRequestConverter<?>> ItemRequestConverter<?> newInstance(Class<IRC> itemRequestConverterClass);
}
class CreatePartRequestConverter implements ItemRequestConverter<ItemRequest>
{
}

class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory 
{
    @Override
    public <IRC extends ItemRequestConverter<?>> ItemRequestConverter<?> newInstance(
        Class<IRC> itemRequestConverterClass)
    {
        if (itemRequestConverterClass.equals(CreatePartRequestConverter.class))
        {
            return new CreatePartRequestConverter();
        }
        return null;
    }
}

如果您还需要有关ItemRequest类的信息,则方法签名可能会开始变得有些讨厌,因此必须更详细地分析应在何处以及如何提供或使用这种类型的信息。


编辑评论:

我认为这不可能以(编译时)类型检查的方式进行。 这里的问题是,在您创建并返回新的ItemRequestConverter ,您不能肯定地说它是类型参数为IRItemRequestConverter 或反过来:在编译​​时,您无法检测到CreatePartRequestConverter的类型参数(即CreatePartRequest )与IR相同。

根据到目前为止讨论的代码片段,我认为在这种情况下应该可以简单地进行转换。 然后,确保强制转换有效的责任留给了实施“运行时类型检查”的人:

if (itemRequestClass.equals(CreatePartRequest.class))
{
    CreatePartRequestConverter result = new CreatePartRequestConverter();
    return (ItemRequestConverter<IR>) result;
}

因为没有什么可以阻止你写作

//                          !!!
if (itemRequestClass.equals(SomeCompletelyDifferentRequest.class))
{
    CreatePartRequestConverter result = new CreatePartRequestConverter();
    return (ItemRequestConverter<IR>) result;
}

因此,这样做应该是有效的:

interface ItemRequestConverter<IR extends ItemRequest>{}
interface ItemRequest{}
interface ItemRequestConverterFactory 
{
    public <IR extends ItemRequest> ItemRequestConverter<IR> 
        newInstance(Class<IR> itemRequestClass);
}

class CreatePartRequest implements ItemRequest {}
class CreatePartRequestConverter 
    implements ItemRequestConverter<CreatePartRequest> {}

class DefaultItemRequestConverterFactory implements ItemRequestConverterFactory 
{
    @Override
    public <IR extends ItemRequest> ItemRequestConverter<IR> newInstance(
            Class<IR> itemRequestClass)
    {
        if (itemRequestClass.equals(CreatePartRequest.class))
        {
            CreatePartRequestConverter result = new CreatePartRequestConverter();
            return (ItemRequestConverter<IR>) result;
        }
        return null;
    }
}

public class GenericFactoryTest
{
    public static void main(String[] args)
    {
        ItemRequestConverterFactory factory = null;
        ItemRequestConverter<CreatePartRequest> converter = 
            factory.newInstance(CreatePartRequest.class);        
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM