在这种情况下,如何正确使用泛型?

时间:2018-07-25 16:57:45

标签: java generics design-patterns interface

下面是我的变压器界面

public interface Transformer<BusinessObject, O extends State>
{
    public O transformToState(BusinessObject input);
}

这是我的变形金刚Impl之一

public class GoldTransformer implements Transformer<BusinessObject, Gold>
{
    @Override
    public Gold transformToState(BusinessObject input) {
        GoldBO goldbo= (GoldBO) input; // redundant casting line
        //do some transformation with BO to make it a state with some business logic
    }
}

这是我的另一个《变形金刚》 Impl

public class SilverTransformer implements Transformer<BusinessObject, Sliver> 
{
    @Override
    public Gold transformToState(BusinessObject input) {
        SilverBO goldbo= (SilverBO) input; // redundant casting line
        // again do some transformation with BO to make it a state with some business logic
    }
}

SilverBOGoldBO都实现BusinessObject,这是一个标记接口。 SilverGold扩展了State。我真的觉得转换很烦人和多余,在这里有没有更好的方法来使用泛型?还是使用更好的模式?我不想对state(即黄金和白银)进行任何更改。

3 个答案:

答案 0 :(得分:5)

您也可以在输入BusinessObject上推广该接口:

public interface Transformer<I extends BusinessObject, O extends State> {
    public O transformToState(I input);
}

public class GoldTransformer implements Transformer<GoldBO, Gold> {    
    @Override
    public Gold transformToState(GoldBO input) {
        // Code...
    }
}

答案 1 :(得分:2)

看起来BusinessObject是一个类,但是您还使用与通用类型参数相同的标识符!在这段代码中,BusinessObject没有引用您的类,它是一个不同的标识符。如果在其他程序包中,则可以通过验证它是否不需要导入来进行验证。

interface Transformer<BusinessObject, O extends State>
{
    public O transformToState(BusinessObject input);
}

这与在语义上相同:

interface Transformer<FlyingSpaghettiMonster, O extends State>
{
    public O transformToState(FlyingSpaghettiMonster input);
}

任何体面的IDE都会为通用类型参数添加不同的颜色,以帮助您区分它们。如下所示,实型参数为白色,而通用类型参数为深绿色:

generic type parameter highlighting in IntelliJ IDEA

虽然您应该更改泛型类型参数以避免混淆,但是从技术上讲,要删除转换,您需要做的就是更改您的转换器实现,如下所示:

public class GoldTransformer implements Transformer<GoldBO, Gold>
{                                                 // ^ changed
    @Override
    public Gold transformToState(GoldBO input) {
                                // ^ changed
    }
}

但是,您可能(也可能是 )也要强制第一类型参数是BusinessObject的子类,否则就有可能创建Transformer<String, Gold> 。为此,请将您的界面更改为:

public interface Transformer<I extends BusinessObject, O extends State>
{
    public O transformToState(I input);
}

I现在是通用类型参数,而BusinessObject是实际类型,它确实引用了您的类。

答案 2 :(得分:1)

也使输入通用:

public interface Transformer<I extends BusinessObject, O extends State> {
    public O transformToState(I input);
}

银色示例:

public class SilverTransformer implements Transformer<SilverBO, Silver> {    

    @Override
    public Silver transformToState(SilverBO input) {
         return new Silver(input); // an example, perform the transformation...
    }   
}

Java 8提供了一种较短的方法

或者,如果您使用Java 8或更高版本,则Transformer<BusinessObject, O extends State>的作用与java.util.Function<BusinessObject, O extends State>完全相同。因此,将不需要该接口。用法非常简洁:

Function<SilverBO, Silver> silverTransformer = (input -> new Silver(input));
Silver silver = silverTransformer.apply(silverBo);

直接在lambda表达式内执行转换。如果转换需要更多行,请使用括号{}return

Function<SilverBO, Silver> silverTransformer = (input -> {
    Silver output = // transformation ... 
    // ... more transformation ...
    return output;
});