【问题标题】:How do I correctly use generics in this case?在这种情况下如何正确使用泛型?
【发布时间】:2019-01-02 14:01:25
【问题描述】:

下面是我的转换器界面

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

这是我的 Transformer 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
    }
}

这是我的另一个 Transformer 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 进行任何更改,即黄金和白银。

【问题讨论】:

  • GoldGoldBO是什么关系?
  • GoldBO 有一些额外的属性,并不是直接复制 Gold。根据业务逻辑,我决定哪些值应该进入黄金状态

标签: java generics design-patterns interface


【解决方案1】:

您也可以在输入 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 都会对泛型类型参数进行不同的着色,以帮助您区分它们。见下文,真正的类型参数是白色的,而泛型类型参数是深绿色的:

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

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

但是,您可能(或可能)还希望强制第一个类型参数是 BusinessObject 的子类,否则可以创建Transformer&lt;String, Gold&gt;。为此,请将您的界面更改为:

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

I 现在是泛型类型参数,而 BusinessObject 是引用您的类的真实类型。

【讨论】:

    【解决方案3】:

    使输入也通用:

    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&lt;BusinessObject, O extends State&gt; 的作用与java.util.Function&lt;BusinessObject, O extends State&gt; 完全相同。因此不需要该接口。用法很简洁:

    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;
    });
    

    【讨论】:

    • 快速问题BusinessObject 是一个标记接口,我的SilverBO 实现了BusinessObject 而不是扩展它。 还能工作吗?
    • @Kid101:查看修订,我在您添加评论前 4 分钟纠正了这个错误 :)
    • 低带宽:)
    猜你喜欢
    • 1970-01-01
    • 2020-08-06
    • 2022-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-22
    • 1970-01-01
    相关资源
    最近更新 更多