30

最近在一次采访中,我被问到一个非常笼统的问题“java中的抽象是什么”。我给出了定义,然后是关于抽象的其他一些问题,例如什么是抽象方法以及抽象方法与具体方法之间的区别等。然后最后面试官要求给出一个实时的例子,什么时候我应该使用或定义一个抽象类。我很困惑。我举了一些例子,但他不相信。

我用谷歌搜索但没有找到真正的解决方案。

那么有人可以给我实时的例子,即当他在他/她的项目中将一个类定义为抽象类时,为什么?

谢谢。

4

5 回答 5

27

从这里找到的一个很好的实时示例:-

抽象类的一个具体示例是一个名为 Animal 的类。你在现实生活中看到很多动物,但动物只有种类。也就是说,你永远不会看着紫色和毛茸茸的东西说“那是一种动物,没有更具体的定义方式”。相反,你会看到一只狗、一只猫或一头猪……所有的动物。关键是,你永远看不到一只动物在四处走动,而不是更具体地说是其他东西(鸭子、猪等)。Animal 是抽象类,Duck/Pig/Cat 都是派生自该基类的类。动物可能会提供一种称为“年龄”的功能,可以为动物增加 1 年的寿命。它还可能提供一个名为“IsDead”的抽象方法,当调用该方法时,它会告诉您动物是否已经死亡。由于 IsDead 是抽象的,每只动物都必须执行它。因此,猫可能会在 14 岁后决定它已经死了,而鸭子可能会在 5 岁后决定它会死。抽象类 Animal 为从它派生的所有类提供 Age 函数,但这些类中的每一个都必须自己实现 IsDead。

一个商业例子

将 List 作为抽象类没有意义,因为与 LinkedList 相比,anArrayList 的工作方式存在根本差异。同样,映射和设置。如果我只是处理一组对象而不关心它是 List、Map 还是 Set,我可以只使用 Collection 接口。

于 2013-09-22T13:56:05.100 回答
8

在这里,关于抽象类的一些事情......

  1. 抽象类是一个不完整的类,所以我们不能实例化它。
  2. 如果方法是抽象的,那么类必须是抽象的。
  3. 在抽象类中,我们同时使用抽象方法和具体方法。
  4. 定义类 abstract 和 final 都是非法的。

实时示例——

如果您想制造一辆新车(WagonX),其中包含其他汽车的所有属性,如颜色、尺寸、引擎等在 WagonX 类中,您将所有预定义的功能用作抽象,而另一个功能是具体的,由您定义。
另一个扩展抽象类 WagonX 的子类,默认情况下它还访问抽象类中实例化的抽象方法。子类还通过创建子类的对象来访问具体方法。
为了代码的可重用性,开发人员主要使用抽象类。

abstract class WagonX
{
   public abstract void model();
   public abstract void color();
   public static void baseEngine()
    {
     // your logic here
    }
   public static void size()
   {
   // logic here
   }
}
class Car extends WagonX
{
public void model()
{
// logic here
}
public void color()
{
// logic here
}
}
于 2014-01-04T06:25:11.753 回答
3

抽象类的最佳示例是GenericServlet. GenericServlet是 的父类HttpServlet。它是一个抽象类。

在自定义 servlet 类中继承“GenericServlet”时,service()必须重写该方法。

于 2014-01-12T14:34:09.403 回答
2

您应该能够从 JDK 本身中引用至少一个。看java.util.collections包装。有几个抽象类。你应该完全理解接口、抽象和具体,Map以及为什么 Joshua Bloch 会这样写。

于 2013-09-22T13:54:04.497 回答
1

我经常将抽象类与模板方法模式结合使用。
在主要抽象类中,我编写了主要算法的骨架,并将抽象方法作为钩子,子类可以在其中进行特定的实现;在编写需要从不同位置(文件、数据库或其他一些来源)读取数据、具有相似处理步骤(可能存在细微差异)和不同输出的数据解析器(或处理器)时,我经常使用它。
这种模式看起来像策略模式,但它给你的粒度更少,并且如果主代码增长太多或需要来自主流的异常(这个考虑来自我的经验),它可能会降级为难以维护的代码。
只是一个小例子:

abstract class MainProcess {
  public static class Metrics {
    int skipped;
    int processed;
    int stored;
    int error;
  }
  private Metrics metrics;
  protected abstract Iterator<Item> readObjectsFromSource();
  protected abstract boolean storeItem(Item item);
  protected Item processItem(Item item) {
    /* do something on item and return it to store, or null to skip */
    return item;
  }
  public Metrics getMetrics() {
    return metrics;
  }
  /* Main method */
  final public void process() {
    this.metrics = new Metrics();
    Iterator<Item> items = readObjectsFromSource();
    for(Item item : items) {
      metrics.processed++;
      item = processItem(item);
      if(null != item) {

        if(storeItem(item))
          metrics.stored++;
        else
          metrics.error++;
      }
      else {
        metrics.skipped++;
      }
    }
  } 
}

class ProcessFromDatabase extends MainProcess {
  ProcessFromDatabase(String query) {
    this.query = query;
  }
  protected Iterator<Item> readObjectsFromSource() {
    return sessionFactory.getCurrentSession().query(query).list();
  }
  protected boolean storeItem(Item item) {
    return sessionFactory.getCurrentSession().saveOrUpdate(item);
  }
}

这里再举一个例子。

于 2013-09-22T20:59:04.440 回答