2012-06-23 40 views
1

我想通用化返回 泛型基类的工厂方法。它的工作原理,但我得到 “BaseClass是一种原始类型...”的警告。Java - 返回通用基类型的工厂方法

我已经通过通用方法, Java文档阅读,但我还没有完全得到如何做到这一点。

下面是一些代码:

级#1

//base abstract class 
public abstract class BaseFormatter<T> 
{ 
    public abstract String formatValue(T value); 
} 

类#2

//two implementations of concrete classes 
public class FooFormatter extends BaseFormatter<Integer> 
{ 
    @Override 
    public String formatValue(Integer value) 
    { 
     //return a formatted String 
    } 
} 

类#3

public class BarFormatter extends BaseFormatter<String> 
{ 
    @Override 
    public String formatValue(String value) 
    { 
     //return a formatted String 
    } 
} 

工厂方法在一个单独的类

public static BaseFormatter getFormatter(Integer unrelatedInteger) 
{ 
    if (FOO_FORMATTER.equals(unrelatedInteger)) 
     return new FooFormatter(); 
    else if (BAR_FORMATTER.equals(unrelatedInteger)) 
     return new BarFormatter(); 
    //else... 
} 

电话工厂方法从其他地方中的代码

BaseFormatter<Integer> formatter = getFormatter(someInteger); 
formatter.formatValue(myIntegerToFormat); 

的问题是getFormatter()方法警告BaseFormatter是 原始类型,它是。我已经尝试过各种各样的东西,比如BaseFormatter 等。当然,我希望返回类型是通用的,如调用方法中声明的 BaseFormatter。

请注意,格式化程序类型不是基于类的类型。例如并非所有Integer 值都使用FooFormatter格式化。有两种或三种不同的方法可以对整数(或字符串或列表)进行格式化。这就是param unrelatedInteger的用途。

在此先感谢您的任何反馈意见。

+0

简单的答案:Java类型系统无法安全地表达您想要的约束。这意味着你不能摆脱这个演员的警告。 – millimoose

回答

0

如果getFormatter在BaseFormatter定义,然后使用:

public static BaseFormatter<T> getFormatter(Integer unrelatedInteger) 

如果getFormatter在另一个类比BaseFormatter定义,然后使用:

public static BaseFormatter<?> getFormatter(Integer unrelatedInteger) 
+0

如果我做BaseFormatter ,我必须这样做:public static BaseFormatter getFormatter(整数转换器)。我不能这样做,因为返回新的FooFormatter()会导致错误。无法从FooFormatter转换为BaseFormatter ,所以这不起作用。 –

+0

@TJJJ看到我的更新 –

+0

我看了你的更新。问题在于:getFormatter在另一个类中定义。如果我返回一个未知类型的BaseFormatter(BaseFormatter ),这个方法很开心。但在调用方法中,我无法执行BaseFormatter formatter = getFormatter(someInteger);我得到一个类型不匹配错误。如果我将其更改为BaseFormatter formatter = getFormatter(someInteger);那么我不能传入一个整数,因为这个类型是未知的,而不是整数。 –

0

你actuaaly说,有没有连接在作为参数传递给getFormatter方法的输入参数BaseFormatterunrelatedInteger之间。

我得到一些其他的警告:

Uncehcked Assignment: BaseFormatter to BaseFormatter<Integer> 

这个警告是比你指定的一个更坏。报告警告说,该用户代码可能尝试插入BaseFormatter<String>BaseFormatter<Integer>,这东西会注意到只能在运行时失败...考虑用户不小心使用你的工厂方法类似这样:

BaseFormatter<Integer> myUnsafeFormatter = 
     FormatterFactory.getFormatter(unrelatedIntegerForBarFormatter); 

编译器可以不涉及unrelatedInteger与参数化类型返回BaseFormatter

另外,我会让用户显式使用具体的格式化构造函数。所有格式化器共享的任何通用代码都可以放入FormatterUtils类(只是不要让该utils类增长太多......)。

0

学术语言中的某些类型系统可以表达所谓的相关和。 Java当然不能;那么明智的是,getFormatter方法返回的对象的类型是什么?我们可以做的最好的是BaseFormatter< ? extends Object >或简称BaseFormatter<?>,因为IntegerString只有Object的共同点。为什么我们必须使用一个整数来决定返回哪个格式化程序,并且如果调用程序不知道格式化程序的类型,为什么调用程序需要一个更强的变量类型而不是BaseFormatter<?>

+0

好吧,从技术上说,它不需要任何东西超过BaseFormatter 。问题在于它使用BaseFormatter作为排序接口,使用适当的数据类型调用相同的format()方法。在它接受Object并将其转换为正确类型之前。当然,这是一个问题,因为它对类抛出异常是开放的。当对此进行通用化时,强制格式(arg)方法的数据类型是合理的。由于不同的格式化程序采用不同的类型,我不得不在超类中使用T.我唯一能想到的另一种方法是(继续下一篇文章) –

+0

替换BaseFormatter formatter = getFormatter(someInteger); 与if语句并实例化正确的格式化程序。它在几个地方叫,所以这是跛脚。我把这些代码放在一个普通的位置上。但是为了使FooFormatter和BarFormatter的工作方式相同(例如相同的方法调用,不同的argtype),它需要一个超类和抽象方法都必须实现。我正在考虑的另一个解决方案是使用CommonFormatter和重载格式(),所以我可以做cf.format(unrelatedInteger,myIntToFormat,cf.format(unrelatedInteger,myStrToFormat)。(继续下一篇文章) –

+0

因为我可以有几个不同的格式(有2个以上,但本例保持为2),这些方法中的每一个都会有一系列if语句,例如if(FOO_FORMATTER.equals(unrelatedInteger)) //做foo格式化; 否则如果(BAR_FORMATTER.equals(unrelatedInteger)) //做酒吧格式化我不喜欢那个,我愿意接受任何人的建议。 –