最近在一次采访中,我被问到一个非常笼统的问题“java中的抽象是什么”。我给出了定义,然后是关于抽象的其他一些问题,例如什么是抽象方法以及抽象方法与具体方法之间的区别等。然后最后面试官要求给出一个实时的例子,什么时候我应该使用或定义一个抽象类。我很困惑。我举了一些例子,但他不相信。
我用谷歌搜索但没有找到真正的解决方案。
那么有人可以给我实时的例子,即当他在他/她的项目中将一个类定义为抽象类时,为什么?
谢谢。
最近在一次采访中,我被问到一个非常笼统的问题“java中的抽象是什么”。我给出了定义,然后是关于抽象的其他一些问题,例如什么是抽象方法以及抽象方法与具体方法之间的区别等。然后最后面试官要求给出一个实时的例子,什么时候我应该使用或定义一个抽象类。我很困惑。我举了一些例子,但他不相信。
我用谷歌搜索但没有找到真正的解决方案。
那么有人可以给我实时的例子,即当他在他/她的项目中将一个类定义为抽象类时,为什么?
谢谢。
从这里找到的一个很好的实时示例:-
抽象类的一个具体示例是一个名为 Animal 的类。你在现实生活中看到很多动物,但动物只有种类。也就是说,你永远不会看着紫色和毛茸茸的东西说“那是一种动物,没有更具体的定义方式”。相反,你会看到一只狗、一只猫或一头猪……所有的动物。关键是,你永远看不到一只动物在四处走动,而不是更具体地说是其他东西(鸭子、猪等)。Animal 是抽象类,Duck/Pig/Cat 都是派生自该基类的类。动物可能会提供一种称为“年龄”的功能,可以为动物增加 1 年的寿命。它还可能提供一个名为“IsDead”的抽象方法,当调用该方法时,它会告诉您动物是否已经死亡。由于 IsDead 是抽象的,每只动物都必须执行它。因此,猫可能会在 14 岁后决定它已经死了,而鸭子可能会在 5 岁后决定它会死。抽象类 Animal 为从它派生的所有类提供 Age 函数,但这些类中的每一个都必须自己实现 IsDead。
一个商业例子:
将 List 作为抽象类没有意义,因为与 LinkedList 相比,anArrayList 的工作方式存在根本差异。同样,映射和设置。如果我只是处理一组对象而不关心它是 List、Map 还是 Set,我可以只使用 Collection 接口。
在这里,关于抽象类的一些事情......
实时示例——
如果您想制造一辆新车(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
}
}
抽象类的最佳示例是GenericServlet
. GenericServlet
是 的父类HttpServlet
。它是一个抽象类。
在自定义 servlet 类中继承“GenericServlet”时,service()
必须重写该方法。
您应该能够从 JDK 本身中引用至少一个。看java.util.collections
包装。有几个抽象类。你应该完全理解接口、抽象和具体,Map
以及为什么 Joshua Bloch 会这样写。
我经常将抽象类与模板方法模式结合使用。
在主要抽象类中,我编写了主要算法的骨架,并将抽象方法作为钩子,子类可以在其中进行特定的实现;在编写需要从不同位置(文件、数据库或其他一些来源)读取数据、具有相似处理步骤(可能存在细微差异)和不同输出的数据解析器(或处理器)时,我经常使用它。
这种模式看起来像策略模式,但它给你的粒度更少,并且如果主代码增长太多或需要来自主流的异常(这个考虑来自我的经验),它可能会降级为难以维护的代码。
只是一个小例子:
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);
}
}
这里再举一个例子。