【问题标题】:Using generic methods as an alternative to overloading?使用泛型方法替代重载?
【发布时间】:2015-08-21 12:06:43
【问题描述】:

重载没问题。但是如果我们认为我们有 两个对象 ObjectA 和 objectB。两者都有“id”和“name”变量。我想编写一个方法(在第三类中),它返回给定对象的名称。编写重载函数让我重复代码。这是一个很好的做法吗? 改用泛型函数不是更好吗?

所以,我知道我可以编写一个重载函数……。像这样:

public String getInfo(ObjectA o){
    if(o.getId()!=1) return o.name;
    return "";
}
public String getInfo(ObjectB o){
    if(o.getId()!=1) return o.name;
    return "";
}

而且效果很好。 但是这两个功能是一样的!唯一的区别是事实,它们需要不同类型的参数。因为它们看起来一样,是不是违反了 DRY 规则? 我尝试编写简单的通用方法,但 IDE 将 that.getId 和 that.name() 标记为错误,并建议将其转换为 ((ObjectA) that).getId() 或 ((ObjectB) that).getId() .我不是在“T that = clazz.cast(o);”行中完成了吗? 我做错了什么?

public <T> String getInfo(Class<T> clazz, Object o) {
              T that = clazz.cast(o);
              if (that.getId()!=1) return that.name;

            return "";
        }

一般来说,我想知道我的想法是否可行。我该如何解决我的错误?更重要的是,这是个好主意吗?还是直接写重载函数更好?

【问题讨论】:

  • 一个典型的解决方案是确保 ObjectA 和 ObjectB 都实现声明 hasName 和 hasId 方法的接口。
  • 鉴于T 被擦除为Object,以上将无法编译,因为Object.getId() 不是实际方法。正如其他人所建议的那样,您需要有一个定义 getId 的通用接口。
  • @AndyTurner 类型擦除在这里没有进入图片,它是纯类型代数。 T上限Object。擦除的后果仅在运行时出现(在某些退化的情况下在编译时,但仅由于 Java 中擦除的特定扭曲)。
  • 非常感谢,没想到答案这么快!两个答案都很好,而且是同时写的。真的我不知道我应该标记哪个! :)
  • 请牢记single responsibility principle。如果ObjectB 的要求发生变化,它的名称被拆分为firstNamelastName 怎么办?接口和ObjectA会怎样?

标签: java oop generics


【解决方案1】:

这两个想法都很糟糕。您的ObjectAObjectB 类应该实现一个定义getId()getName() 方法的通用接口。

那么你就可以用一个方法逃脱:

public String getInfo(Interface o){
    if(o.getId()!=1) return o.getName();
    return "";
}

【讨论】:

  • 或者只是让getInfo() 成为具有默认实现的接口上的方法?
  • @Kevin 我没有指定将单个方法放在哪里;)但我很可能不会在这样的情况下使用默认方法(尽管不清楚这里的“情况”是什么)。这段代码看起来很普通,很容易用“空”界面解决。
【解决方案2】:

您的案例非常适合进行接口编程。创建接口并移动常用方法。

public String getInfo(InterfaceAB in){
    if(in.getId()!=1) return in.getName();
    return "";
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    相关资源
    最近更新 更多