抽象类的目的/用途是什么?(寻找现实世界的例子。)

3

请问有人能给我展示一个Java中的抽象类的例子吗?最好是真实世界应用的样例(而不是教科书上的范例)。

谢谢!


你所说的“实时示例”是什么意思? - akf
@akf,我认为他指的是现实世界。 - Mike Sherov
@Mike Sherov:哈!我已经进行了编辑,当我回来时,你的评论已经在那里了。我同意你的解释并进行了相应的编辑。不过可能仍然是重复内容。 :) - Esteban Araya
@akf - 这是许多母语不是英语的人常犯的错误。他可能是指“现实生活”。 - Stephen C
明白了。我为后人添加了一个示例。顺便说一句,编辑得很好。 - akf
5个回答

6

阅读有关抽象方法和类的教程。

首先,您声明一个抽象类GraphicObject,它提供成员变量和方法,这些成员变量和方法完全由所有子类共享,例如当前位置和moveTo方法。 GraphicObject还声明了一些抽象方法,如draw或resize等方法,这些方法需要由所有子类实现,但必须以不同的方式实现。 GraphicObject类可能如下所示:

abstract class GraphicObject {
    int x, y;
    ...
    void moveTo(int newX, int newY) {
        ...
    }
    abstract void draw();
    abstract void resize();
}

每个非抽象的GraphicObject子类,如Circle和Rectangle,必须提供draw和resize方法的实现:

class Circle extends GraphicObject {
    void draw() {
        ...
    }
    void resize() {
        ...
    }
}
class Rectangle extends GraphicObject {
    void draw() {
        ...
    }
    void resize() {
        ...
    }
}

进一步说,抽象类的方法(在这里我们考虑 moveTo)可以调用 drawresize,即使抽象类没有为它们编写代码。然后扩展类以自己的方式实现它们,但是 moveTo 方法对于所有扩展类始终是相同的。这样,您可以将公共代码保留在抽象类中,但仍然可以通过将部分行为移动到抽象方法中,在不同的扩展类中使其表现不同,由子类选择如何实现。 - Andrei Fierbinteanu

3

举个现实世界的例子,不妨看看java.util.AbstractCollection


2
在Java编程语言中,抽象类仅作为父类或基类使用。
子类派生来实现从抽象类(基类)继承的方法。抽象类不能直接实例化,必须先扩展基类,然后实例化(创建对象)。抽象类具有通用性,实现那些由子类共同使用且具有通用实现的方法。

例如:

abstract class A {
         public abstract abs_value();

         void show() 
                   {
                   System.out.println("This is an abstract class");
                   }
               }

2

举个实际的例子来说明抽象类,我们来看一下AbstractTableModelAbstractTableModel提供了TableModel接口的实现(用于与JTable一起使用)。TableModel定义了以下方法:

public boolean isCellEditable(int rowIndex, int columnIndex);
public Class<?> getColumnClass(int columnIndex);
public int getColumnCount();
public int getRowCount();
public Object getValueAt(int rowIndex, int columnIndex);
public String getColumnName(int columnIndex);
public void addTableModelListener(TableModelListener l);
public void removeTableModelListener(TableModelListener l);
public void setValueAt(Object aValue, int rowIndex, int columnIndex);

AbstractTableModel提供了所有方法的默认实现,除了其中三个方法(getRowCountgetColumnCountgetValueAt),这迫使扩展类至少提供实现来定义表格的大小并提供数据。它还提供了良好的默认监听器处理以及一堆方便的方法来向这些监听器发送事件。


1

我认为这是一个常见的现实世界例子:

这可能与您要求的有些远,但假设我们正在使用像Hibernate这样的ORM框架(不需要真正担心它是什么或者意味着什么,只需知道我们基本上将从数据库中插入/更新和检索对象)。

对于我们要插入的每个表,我们都将有一个唯一的数据库访问对象(DAO)来执行我们所需的一组数据库操作,但重要的是要注意所有DAO都将执行一些类似的任务,因此这就是抽象类可以帮助我们的地方。我们可以声明一个AbstractBaseDao类,它概述了我们可能需要的所有DAO的一些基本操作:

public class AbstractBaseDao {
    public void saveOrUpdate(Object o){
         //save or update object from database
    }

    public void loadAll(Class clazz){
        //Load all from database
    }

    public Object loadById(Class clazz, Long id){
       // Retrieve object by Id from database
    }

    // Additional common methods
}

所以再次强调,对于这个例子,这些方法的实现方式并不是非常重要,只需要意识到所有 DAO 都需要这些方法,并且抽象类可以在类之间进行代码重用。

有了我们的 BaseDao,我们现在可以自由地为每个表创建具体而特定的 DAO,同时仍具有我们所需的共同功能:

public class PersonDao extends AbstractBaseDao{
     public List<People> listAllPersonsByLastName(String lastName){
         //Load people by last names from database
     }

     public List<People> listAllPersonsByBirthYear(Date date){
        //List people by birth year from database
     }
}

现在,PersonDao可以执行任何特定的任务,我们不会浪费时间重写已经编写过的代码。这是代码重用的一个很好的例子。

我认为这是在行业中使用抽象类的一个相当普遍的例子,所以我希望它能对你寻找的内容有所帮助。


1
好的例子,如果您使用泛型会更好。 public class AbstractBaseDao<T> { [...] public T loadById(Class clazz, Long id) {[...] - Christian Kuetbach
我不理解你的例子 - 你的“AbstractBaseDao”不是一个抽象类。这与问题有什么关系?如果这只是一个打字错误,它应该是一个抽象类 - 如果AbstractBaseDao中的所有方法都是具体的,为什么要将该类定义为抽象的? - SteveT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接