java中有哪些抽象类的实例?

时间:2022-09-25 12:15:06

When and why should abstract classes be used? I would like to see some practical examples of their uses. Also, what is the difference between abstract classes and interfaces?

何时以及为什么要使用抽象类?我想看一些他们使用的实例。还有,抽象类和接口之间的区别是什么?

11 个解决方案

#1


9  

Abstract classes are "half-implementations" of a class. They can be partially implemented with some generic functionality, but leave part of the implementation to the inheriting classes. You could have an abstract class called Animal that has implemented some generic behavior/values such as Age, Name, SetAge(...). You can also have methods that are not implemented (they are abstract), much like an interface.

抽象类是类的“半实现”。它们可以通过一些通用功能实现部分实现,但将部分实现留给了继承类。您可以有一个名为Animal的抽象类,它实现了一些通用的行为/值,比如Age、Name、SetAge(…)。您还可以有一些未实现的方法(它们是抽象的),很像一个接口。

Interfaces are simply contracts that specify behaviors that should be available for a class. You could have an interface such as IWalker that requires public method Walk(), but no specifics on how it is implemented.

接口是一种简单的契约,它指定应该为类提供的行为。您可以有一个接口,比如IWalker,它需要public method Walk(),但是没有具体的实现方式。

#2


5  

Abstract Classes versus Interfaces

Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

与接口不同,抽象类可以包含非静态和最终的字段,它们可以包含实现的方法。此类抽象类与接口类似,只是它们提供了部分实现,将其留给子类来完成实现。如果一个抽象类只包含抽象的方法声明,那么它应该被声明为一个接口。

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.

在类层次结构中的任何地方都可以实现多个接口,无论它们是否以任何方式相互关联。举个例子,想想可比性的或可克隆的。

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).

相比之下,抽象类通常被子类化来共享实现。一个抽象类被类似的类子类化,这些类有很多共同之处(抽象类的实现部分),但也有一些不同(抽象方法)。

An Abstract Class Example

In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. These objects all have certain states (for example: position, orientation, line color, fill color) and behaviors (for example: moveTo, rotate, resize, draw) in common. Some of these states and behaviors are the same for all graphic objects—for example: position, fill color, and moveTo. Others require different implementations—for example, resize or draw. All GraphicObjects must know how to draw or resize themselves; they just differ in how they do it. This is a perfect situation for an abstract superclass. You can take advantage of the similarities and declare all the graphic objects to inherit from the same abstract parent object—for example, GraphicObject, as shown in the following figure.

在面向对象的绘图应用程序中,您可以绘制圆圈、矩形、直线、Bezier曲线和许多其他图形对象。这些对象都有特定的状态(例如:位置、方向、线条颜色、填充颜色)和行为(例如:moveTo、rotate、resize、draw)。其中一些状态和行为对所有图形对象都是相同的,例如:位置、填充颜色和mo否决权。其他的则需要不同的实现——例如,调整大小或绘制。所有图形对象必须知道如何绘制或调整自身大小;他们只是在做这件事上有所不同。对于抽象超类来说,这是一个完美的情况。您可以利用相似点并声明所有图形对象从相同的抽象父对象(例如,GraphicObject)继承,如下图所示。

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject http://java.sun.com/docs/books/tutorial/figures/java/classes-graphicObject.gif

类矩形、线条、Bezier和Circle继承自GraphicObject http://java.sun.com/docs/books/tutorial/figures/java/class.graphicobject.gif。

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

类矩形、直线、Bezier和Circle从GraphicObject继承。

[...]

[…]

Source: The Java™ Tutorials

来源:Java™教程

#3


5  

Classes that are entirely abstract (all methods are abstract) are (almost) the same as interfaces (the major difference being they can contain fields and non-public abstract methods, which interfaces cannot). The difference is when you have an abstract class which contains a method which has some common functionality which will be the same for all derived children.

完全抽象的类(所有方法都是抽象的)几乎与接口相同(主要区别在于它们可以包含字段和非公共抽象方法,而接口不能)。区别在于,当您有一个抽象类时,其中包含一个方法,该方法具有一些共同的功能,对于所有派生的子元素都是相同的。

If you want to model a Filesystem, for example, you know that, regardless of the object type, you will have a path for an item. You'd want to have a common implementation for getting that path (no point in writing the same thing over and over again), and leave anything special for the children to implement.

例如,如果您想建模一个文件系统,您就知道,不管对象类型是什么,您都将有一个项目的路径。您希望有一个通用的实现来获得这条路径(不需要反复编写相同的东西),并留下任何特殊的东西给孩子们去实现。

#4


3  

Surprisingly, many examples/explanations given here do not provide good arguments for using an abstract class. Merely putting common fields/methods in a superclass does not require it to be abstract. Also (start rant), shame on supposedly knowledgeable engineers still coming up with Animal / Vehicle / Figure hierarchies to 'explain' object oriented concepts. These types of examples are very misleading because they point you in the wrong direction; you generally should NOT favour straight subclassing because it creates a very tight coupling between the classes. Rather use collaboration (rant ends).

令人惊讶的是,这里给出的许多示例/解释并没有提供使用抽象类的好理由。仅仅将普通字段/方法放在超类中不需要抽象。还有(开始咆哮),对那些有经验的工程师们的羞辱,他们仍然会提出动物/车辆/图形层次结构来“解释”面向对象的概念。这些类型的例子很容易误导人,因为它们指向错误的方向;通常,您不应该支持直接子类化,因为它在类之间创建了一个非常紧密的耦合。而是使用协作(咆哮结束)。

So what do I think is a good use case for an abstract class? One of my favorite examples is an application of the 'template method' GoF pattern. Here you want to specify the generic flow of an algorithm once, but allow multiple implementations of the individual steps. Here an example I just put together of a VirusScanEngine containing the main virus scanning algorithm (find the next virus, either delete or report it, continue until scan is complete), and a LinearVirusScanner which implements the required algorithm steps (findVirus, deleteVirus and reportVirus). My apologies to all developers really working on virus scanning software for this horrendous simplification.

那么,对于抽象类来说,我认为什么是一个好的用例呢?我最喜欢的一个例子是“模板方法”GoF模式的应用。在这里,您需要指定算法的通用流程,但允许实现单个步骤的多个实现。这里有一个例子,我刚把一个病毒扫描引擎放在一起,它包含了主病毒扫描算法(查找下一个病毒,或者删除或报告它,直到扫描完成为止),还有一个线性病毒扫描程序,它实现了所需的算法步骤(findVirus, deleteVirus和reportVirus)。我向所有的开发人员道歉,他们真的在用病毒扫描软件进行这种可怕的简化。

import java.util.Arrays;

public abstract class VirusScanEngine {

    public static void main(String[] args) {

        byte[] memory = new byte[] { 'a', 'b', 'c', 'M', 'e', 'l', 'i', 's', 's',
                'a' , 'd', 'e', 'f', 'g'};
        System.out.println("Before: " + Arrays.toString(memory));
        new LinearVirusScanner().scan(memory, Action.DELETE);
        System.out.println("After: " + Arrays.toString(memory));
    }

    public enum Action {
        DELETE, REPORT
    };

    public boolean scan(byte[] memory, Action action) {

        boolean virusFound = false;
        int index = 0;
        while (index < memory.length) {

            int size = findVirus(memory, index);
            if (size > 0) {
                switch (action) {

                case DELETE:
                    deleteVirus(memory, index, size);
                    break;
                case REPORT:
                    reportVirus(memory, index, size);
                    break;
                }
                index += size;
            }
            index++;
        }
        return virusFound;
    }

    abstract int findVirus(byte[] memory, int startIndex);

    abstract void reportVirus(byte[] memory, int startIndex, int size);

    abstract void deleteVirus(byte[] memory, int startIndex, int size);
}

and

public class LinearVirusScanner extends VirusScanEngine {

    private static final byte[][] virusSignatures = new byte[][] {
            new byte[] { 'I', 'L', 'O', 'V', 'E', 'Y', 'O', 'U' },
            new byte[] { 'M', 'e', 'l', 'i', 's', 's', 'a' } };

    @Override
    int findVirus(byte[] memory, int startIndex) {

        int size = 0;
        signatures: for (int v = 0; v < virusSignatures.length; v++) {

            scan: {
                for (int t = 0; t < virusSignatures[v].length; t++) {

                    if (memory[startIndex + t] != virusSignatures[v][t]) {
                        break scan;
                    }
                }
                // virus found
                size = virusSignatures[v].length;
                break signatures;
            }
        }
        return size;
    }

    @Override
    void deleteVirus(byte[] memory, int startIndex, int size) {

        for (int n = startIndex; n < startIndex + size - 1; n++) {
            memory[n] = 0;
        }
    }

    @Override
    void reportVirus(byte[] memory, int startIndex, int size) {

        System.out.println("Virus found at position " + startIndex
                + " with length " + size);
    }
}

#5


3  

As KLE correctly explained, the main difference between interface and abstract class is that an abstract class may contain fields and method bodies, while an interface may only contain method signatures (and constants, i.e. public static final fields).

正如KLE所正确解释的那样,接口和抽象类的主要区别在于抽象类可能包含字段和方法体,而接口可能只包含方法签名(和常量,即公共静态final字段)。

Another important distinction is that a class can implement multiple interfaces, but it can only (directly) inherit from one class (abstract or not). So for things which people will probably use in addition to other functionality, an interface makes more sense than an abstract class. See e.g. the interfaces Comparable in the JDK.

另一个重要的区别是类可以实现多个接口,但是它只能(直接)从一个类继承(抽象的或不抽象的)。因此,对于人们可能会在其他功能之外使用的东西,接口比抽象类更有意义。参见:在JDK中类似的接口。

As an example:

作为一个例子:

In the system we develop, we have a class for starting a data import. We have many different kinds of data imports, but most have some things in common: They read data from a file, they write it to the database, they produce an import protocol etc.

在我们开发的系统中,我们有一个用于启动数据导入的类。我们有许多不同类型的数据导入,但大多数都有一些共同之处:他们从一个文件中读取数据,然后将其写入数据库,然后生成一个导入协议等等。

So we have an abstract class "Import", which contains implemented methods for things like writing protocol entries, finding all files to import, deleting processed import files etc. The specifics will be different for each import, so there are abstract methods that serve as extension hooks, e.g. getFilenamePattern() which is used by the reading method to find the files that can be imported. getFilenamePattern is implemented in the concrete subclass, depending on what kinds of files need to be imported.

我们有一个抽象类“进口”,其中包含诸如写作方法实现协议条目,发现所有文件导入,删除处理导入文件等等。每个进口的细节会有所不同,所以有抽象方法,作为扩展挂钩,例如getFilenamePattern()使用的阅读方法来找到可以导入的文件。在具体的子类中实现了getFilenamePattern,这取决于需要导入的文件类型。

That way, the shared import functionality is in one place, while the specifics for one kind of import are separate.

这样,共享的导入功能就在一个地方,而一种导入的细节是分开的。

#6


2  

http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html

http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html

http://java.sun.com/docs/books/tutorial/java/concepts/interface.html

http://java.sun.com/docs/books/tutorial/java/concepts/interface.html

In short, an abstract class can be partially implemented, an interface cannot. More details in the links above.

简而言之,一个抽象类可以部分实现,一个接口不能。更多细节在上面的链接。

#7


2  

If you need to wrap your head around the concept of abstract classes, take a look at the Swing UI toolkit (or at AWT) in the standard library.

如果您需要围绕抽象类的概念进行包装,请查看标准库中的Swing UI工具包(或AWT)。

Because you can imagine what can be visualized (e.g., a button, a label), it's easy to contrast it with the things that can't be instantiated (e.g., a JComponent).

因为您可以想象什么可以可视化(例如,一个按钮,一个标签),很容易将它与不能实例化的东西(例如,JComponent)进行对比。

#8


2  

An interface contains no implementation at all.

一个接口不包含任何实现。

An abstract class may contain some implementation, that is useful to all subclasses, but not be complete : it needs to be completed in some way in the subclasses.
Where the interface lets you use polymorphism on several classes, abstract class also lets them reuse code.

一个抽象类可能包含一些实现,它对所有子类都有用,但不完整:它需要在子类中以某种方式完成。如果接口允许您在多个类上使用多态性,那么抽象类还允许它们重用代码。

     public abstract class Figure {
        protected Point position;

        public abstract void draw();
     }

     public class Square extends Figure {
       // position is usable

       public void draw() {
         // this method must be implemented, for Square not to be abstract
       }

       // here is other code
     }

Another difference is that a class can only have one superclass, but implements many interfaces. This can be a limiting factor.

另一个区别是类只能有一个超类,但是实现了许多接口。这可能是一个限制因素。

#9


2  

You can restrict the order of execution of an instruction with specific steps, but allow delegation for the behavior of each step:

您可以通过特定的步骤限制指令的执行顺序,但是允许每个步骤的行为的授权:

public abstract class Instruction {

    void perform() {
        firstStep();
        secondStep();
        thirdStep();
    }

    abstract void firstStep();

    abstract void secondStep();

    abstract void thirdStep();

}

#10


1  

When and why should abstract classes be used?

何时以及为什么要使用抽象类?

Below post answers your query:

以下是您的查询:

Interface vs Abstract Class (general OO)

接口vs抽象类(通用OO)

I would like to see some practical examples of their uses.

我想看一些他们使用的实例。

When You want to share code among several closely related classes

当您想要在几个紧密相关的类*享代码时。

One practical example : Template method implementation in JDK Reader.java class

一个实际的例子:JDK阅读器中的模板方法实现。java类

Have a look at below post:

请看下面的帖子:

Template design pattern in JDK, could not find a method defining set of methods to be executed in order

在JDK中模板设计模式,无法找到一个方法来定义要按顺序执行的方法。

what is the difference between abstract classes and interfaces?

抽象类和接口的区别是什么?

Refer to this post:

请参考这篇文章:

How should I have explained the difference between an Interface and an Abstract class?

我应该如何解释接口和抽象类之间的区别?

#11


0  

In my own thinking, the correct way is to approach this question is to determine the context you are dealing with regarding the domain or entity objects first, namely what is your use case?

在我自己的想法中,正确的方法是解决这个问题,就是要确定你首先要处理的领域或实体对象的上下文,即你的用例是什么?

In my personal experience, I do this using a top down and then bottom up approach. I start looking for inheritance by looking at the use case and seeing what classes I will need. Then I look to see if there is a superClassOrInterfaceType (since both classes and interfaces define types, I'm combining them into a one word for simplicity. Hopefully it doesn't make it more confusing) domain object that would encompass all the objects, as in a superClassOrInterfaceType of vehicle if I'm working on a use case dealing with subtypeClassOrInterfaceTypes like: cars, trucks, jeeps, and motorcycles for example. If there is a hierarchy relationship, then I define the superClassOrInterfaceType and subtypeClassOrInterfaceTypes.

在我个人的经验中,我使用自上而下和自下而上的方法。通过查看用例并查看我需要的类,我开始寻找继承。然后,我想看看是否有超类orinterfacetype(因为类和接口都定义了类型,我将它们组合成一个简单的词)。希望它不会使它变得更加混乱)域对象,它将包含所有对象,就像在一个超classorinterfacetype of vehicle中,如果我在处理一个用例来处理像:汽车、卡车、吉普车和摩托车这样的子类型的类型。如果存在层次关系,那么我定义超类或子类型的类型。

As I said, what I generally do first is to look for a common domain superClassOrInterfaceType for the objects I'm dealing with. If so, I look for common method operations between the subtypeClassOrInterfaceTypes. If not, I look to see if there are common method implementations, because even though you may have a superClassOrInterfaceType and may have common methods, the implementations may not favor code reuse. At this point, if I have common methods, but no common implementations, I lean towards an interface. However, with this simplistic example, I should have some common methods with some common implementations between the vehicle subtypeClassOrInterfaceTypes that I can reuse code with.

正如我所说的,我通常首先要寻找的是我正在处理的对象的一个通用的域超classorinterfacetype。如果是这样,我将在子类型匹配类型之间寻找常见的方法操作。如果没有,我想看看是否有通用的方法实现,因为即使您可能有一个超类orinterfacetype,并且可能有通用的方法,但是实现可能不支持代码重用。在这一点上,如果我有通用的方法,但是没有通用的实现,我倾向于一个接口。但是,通过这个简单的示例,我应该有一些常见的方法,在汽车的子类型组合接口类型之间有一些常见的实现,我可以重用代码。

On the other hand, if there is no inheritance structure, then I start from the bottom up to see if there are common methods. If there are no common methods and no common implementations, then I opt for a concrete class.

另一方面,如果没有继承结构,那么我就从底部开始,看看是否有通用的方法。如果没有通用的方法,也没有通用的实现,那么我选择一个具体的类。

Generally, if there is inheritance with common methods and common implementations and a need for multiple subtype implementation methods in the same subtype, then I go with an abstract class, which is rare, but I do use it. If you just go with Abstract classes just because there is inheritance, you can run into problems if the code changes a lot. This is detailed very well in the example here: Interfaces vs Abstract Classes in Java, for the different types of domain objects of motors. One of them required a dual powered motor, that required multiple subtype implementation methods to be used in a single subtype class. In other words, a single class needed implementation methods from both solar powered and battery powered motors, which is modeling behaviors and not something you want to do with Abstract classes.

一般来说,如果在相同的子类型中有通用方法和通用实现的继承和对多个子类型实现方法的需求,那么我就会使用一个抽象类,这很少见,但是我确实使用了它。如果仅仅因为有继承而使用抽象类,那么如果代码更改很多,就会遇到问题。其中一个需要双动力马达,这需要在一个子类中使用多个子类型实现方法。换句话说,一个单独的类需要来自太阳能和电池驱动的马达的实现方法,它是建模行为,而不是你想要用抽象类做的事情。

To sum it all up, as a rule you want to define behaviors (what the objects will do) with interfaces and not in Abstract classes. Abstract classes focus on an implementation hierarchy and code reuse.

总的来说,作为一个规则,您希望定义行为(对象将做什么)与接口,而不是抽象类。抽象类关注于实现层次结构和代码重用。

Here are some links that go into greater details on this.

这里有一些关于这个的更详细的链接。

Thanks Type & Gentle Class

谢谢类型和温和的课程。

The Magic behind Subtype Polymorphism

子类型多态性背后的神奇。

Maximize Flexibility with Interfaces & Abstract Classes

最大化的灵活性与接口和抽象类。

Interfaces vs Abstract Classes in Java

接口与Java中的抽象类。

#1


9  

Abstract classes are "half-implementations" of a class. They can be partially implemented with some generic functionality, but leave part of the implementation to the inheriting classes. You could have an abstract class called Animal that has implemented some generic behavior/values such as Age, Name, SetAge(...). You can also have methods that are not implemented (they are abstract), much like an interface.

抽象类是类的“半实现”。它们可以通过一些通用功能实现部分实现,但将部分实现留给了继承类。您可以有一个名为Animal的抽象类,它实现了一些通用的行为/值,比如Age、Name、SetAge(…)。您还可以有一些未实现的方法(它们是抽象的),很像一个接口。

Interfaces are simply contracts that specify behaviors that should be available for a class. You could have an interface such as IWalker that requires public method Walk(), but no specifics on how it is implemented.

接口是一种简单的契约,它指定应该为类提供的行为。您可以有一个接口,比如IWalker,它需要public method Walk(),但是没有具体的实现方式。

#2


5  

Abstract Classes versus Interfaces

Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

与接口不同,抽象类可以包含非静态和最终的字段,它们可以包含实现的方法。此类抽象类与接口类似,只是它们提供了部分实现,将其留给子类来完成实现。如果一个抽象类只包含抽象的方法声明,那么它应该被声明为一个接口。

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.

在类层次结构中的任何地方都可以实现多个接口,无论它们是否以任何方式相互关联。举个例子,想想可比性的或可克隆的。

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).

相比之下,抽象类通常被子类化来共享实现。一个抽象类被类似的类子类化,这些类有很多共同之处(抽象类的实现部分),但也有一些不同(抽象方法)。

An Abstract Class Example

In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. These objects all have certain states (for example: position, orientation, line color, fill color) and behaviors (for example: moveTo, rotate, resize, draw) in common. Some of these states and behaviors are the same for all graphic objects—for example: position, fill color, and moveTo. Others require different implementations—for example, resize or draw. All GraphicObjects must know how to draw or resize themselves; they just differ in how they do it. This is a perfect situation for an abstract superclass. You can take advantage of the similarities and declare all the graphic objects to inherit from the same abstract parent object—for example, GraphicObject, as shown in the following figure.

在面向对象的绘图应用程序中,您可以绘制圆圈、矩形、直线、Bezier曲线和许多其他图形对象。这些对象都有特定的状态(例如:位置、方向、线条颜色、填充颜色)和行为(例如:moveTo、rotate、resize、draw)。其中一些状态和行为对所有图形对象都是相同的,例如:位置、填充颜色和mo否决权。其他的则需要不同的实现——例如,调整大小或绘制。所有图形对象必须知道如何绘制或调整自身大小;他们只是在做这件事上有所不同。对于抽象超类来说,这是一个完美的情况。您可以利用相似点并声明所有图形对象从相同的抽象父对象(例如,GraphicObject)继承,如下图所示。

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject http://java.sun.com/docs/books/tutorial/figures/java/classes-graphicObject.gif

类矩形、线条、Bezier和Circle继承自GraphicObject http://java.sun.com/docs/books/tutorial/figures/java/class.graphicobject.gif。

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

类矩形、直线、Bezier和Circle从GraphicObject继承。

[...]

[…]

Source: The Java™ Tutorials

来源:Java™教程

#3


5  

Classes that are entirely abstract (all methods are abstract) are (almost) the same as interfaces (the major difference being they can contain fields and non-public abstract methods, which interfaces cannot). The difference is when you have an abstract class which contains a method which has some common functionality which will be the same for all derived children.

完全抽象的类(所有方法都是抽象的)几乎与接口相同(主要区别在于它们可以包含字段和非公共抽象方法,而接口不能)。区别在于,当您有一个抽象类时,其中包含一个方法,该方法具有一些共同的功能,对于所有派生的子元素都是相同的。

If you want to model a Filesystem, for example, you know that, regardless of the object type, you will have a path for an item. You'd want to have a common implementation for getting that path (no point in writing the same thing over and over again), and leave anything special for the children to implement.

例如,如果您想建模一个文件系统,您就知道,不管对象类型是什么,您都将有一个项目的路径。您希望有一个通用的实现来获得这条路径(不需要反复编写相同的东西),并留下任何特殊的东西给孩子们去实现。

#4


3  

Surprisingly, many examples/explanations given here do not provide good arguments for using an abstract class. Merely putting common fields/methods in a superclass does not require it to be abstract. Also (start rant), shame on supposedly knowledgeable engineers still coming up with Animal / Vehicle / Figure hierarchies to 'explain' object oriented concepts. These types of examples are very misleading because they point you in the wrong direction; you generally should NOT favour straight subclassing because it creates a very tight coupling between the classes. Rather use collaboration (rant ends).

令人惊讶的是,这里给出的许多示例/解释并没有提供使用抽象类的好理由。仅仅将普通字段/方法放在超类中不需要抽象。还有(开始咆哮),对那些有经验的工程师们的羞辱,他们仍然会提出动物/车辆/图形层次结构来“解释”面向对象的概念。这些类型的例子很容易误导人,因为它们指向错误的方向;通常,您不应该支持直接子类化,因为它在类之间创建了一个非常紧密的耦合。而是使用协作(咆哮结束)。

So what do I think is a good use case for an abstract class? One of my favorite examples is an application of the 'template method' GoF pattern. Here you want to specify the generic flow of an algorithm once, but allow multiple implementations of the individual steps. Here an example I just put together of a VirusScanEngine containing the main virus scanning algorithm (find the next virus, either delete or report it, continue until scan is complete), and a LinearVirusScanner which implements the required algorithm steps (findVirus, deleteVirus and reportVirus). My apologies to all developers really working on virus scanning software for this horrendous simplification.

那么,对于抽象类来说,我认为什么是一个好的用例呢?我最喜欢的一个例子是“模板方法”GoF模式的应用。在这里,您需要指定算法的通用流程,但允许实现单个步骤的多个实现。这里有一个例子,我刚把一个病毒扫描引擎放在一起,它包含了主病毒扫描算法(查找下一个病毒,或者删除或报告它,直到扫描完成为止),还有一个线性病毒扫描程序,它实现了所需的算法步骤(findVirus, deleteVirus和reportVirus)。我向所有的开发人员道歉,他们真的在用病毒扫描软件进行这种可怕的简化。

import java.util.Arrays;

public abstract class VirusScanEngine {

    public static void main(String[] args) {

        byte[] memory = new byte[] { 'a', 'b', 'c', 'M', 'e', 'l', 'i', 's', 's',
                'a' , 'd', 'e', 'f', 'g'};
        System.out.println("Before: " + Arrays.toString(memory));
        new LinearVirusScanner().scan(memory, Action.DELETE);
        System.out.println("After: " + Arrays.toString(memory));
    }

    public enum Action {
        DELETE, REPORT
    };

    public boolean scan(byte[] memory, Action action) {

        boolean virusFound = false;
        int index = 0;
        while (index < memory.length) {

            int size = findVirus(memory, index);
            if (size > 0) {
                switch (action) {

                case DELETE:
                    deleteVirus(memory, index, size);
                    break;
                case REPORT:
                    reportVirus(memory, index, size);
                    break;
                }
                index += size;
            }
            index++;
        }
        return virusFound;
    }

    abstract int findVirus(byte[] memory, int startIndex);

    abstract void reportVirus(byte[] memory, int startIndex, int size);

    abstract void deleteVirus(byte[] memory, int startIndex, int size);
}

and

public class LinearVirusScanner extends VirusScanEngine {

    private static final byte[][] virusSignatures = new byte[][] {
            new byte[] { 'I', 'L', 'O', 'V', 'E', 'Y', 'O', 'U' },
            new byte[] { 'M', 'e', 'l', 'i', 's', 's', 'a' } };

    @Override
    int findVirus(byte[] memory, int startIndex) {

        int size = 0;
        signatures: for (int v = 0; v < virusSignatures.length; v++) {

            scan: {
                for (int t = 0; t < virusSignatures[v].length; t++) {

                    if (memory[startIndex + t] != virusSignatures[v][t]) {
                        break scan;
                    }
                }
                // virus found
                size = virusSignatures[v].length;
                break signatures;
            }
        }
        return size;
    }

    @Override
    void deleteVirus(byte[] memory, int startIndex, int size) {

        for (int n = startIndex; n < startIndex + size - 1; n++) {
            memory[n] = 0;
        }
    }

    @Override
    void reportVirus(byte[] memory, int startIndex, int size) {

        System.out.println("Virus found at position " + startIndex
                + " with length " + size);
    }
}

#5


3  

As KLE correctly explained, the main difference between interface and abstract class is that an abstract class may contain fields and method bodies, while an interface may only contain method signatures (and constants, i.e. public static final fields).

正如KLE所正确解释的那样,接口和抽象类的主要区别在于抽象类可能包含字段和方法体,而接口可能只包含方法签名(和常量,即公共静态final字段)。

Another important distinction is that a class can implement multiple interfaces, but it can only (directly) inherit from one class (abstract or not). So for things which people will probably use in addition to other functionality, an interface makes more sense than an abstract class. See e.g. the interfaces Comparable in the JDK.

另一个重要的区别是类可以实现多个接口,但是它只能(直接)从一个类继承(抽象的或不抽象的)。因此,对于人们可能会在其他功能之外使用的东西,接口比抽象类更有意义。参见:在JDK中类似的接口。

As an example:

作为一个例子:

In the system we develop, we have a class for starting a data import. We have many different kinds of data imports, but most have some things in common: They read data from a file, they write it to the database, they produce an import protocol etc.

在我们开发的系统中,我们有一个用于启动数据导入的类。我们有许多不同类型的数据导入,但大多数都有一些共同之处:他们从一个文件中读取数据,然后将其写入数据库,然后生成一个导入协议等等。

So we have an abstract class "Import", which contains implemented methods for things like writing protocol entries, finding all files to import, deleting processed import files etc. The specifics will be different for each import, so there are abstract methods that serve as extension hooks, e.g. getFilenamePattern() which is used by the reading method to find the files that can be imported. getFilenamePattern is implemented in the concrete subclass, depending on what kinds of files need to be imported.

我们有一个抽象类“进口”,其中包含诸如写作方法实现协议条目,发现所有文件导入,删除处理导入文件等等。每个进口的细节会有所不同,所以有抽象方法,作为扩展挂钩,例如getFilenamePattern()使用的阅读方法来找到可以导入的文件。在具体的子类中实现了getFilenamePattern,这取决于需要导入的文件类型。

That way, the shared import functionality is in one place, while the specifics for one kind of import are separate.

这样,共享的导入功能就在一个地方,而一种导入的细节是分开的。

#6


2  

http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html

http://java.sun.com/docs/books/tutorial/java/IandI/abstract.html

http://java.sun.com/docs/books/tutorial/java/concepts/interface.html

http://java.sun.com/docs/books/tutorial/java/concepts/interface.html

In short, an abstract class can be partially implemented, an interface cannot. More details in the links above.

简而言之,一个抽象类可以部分实现,一个接口不能。更多细节在上面的链接。

#7


2  

If you need to wrap your head around the concept of abstract classes, take a look at the Swing UI toolkit (or at AWT) in the standard library.

如果您需要围绕抽象类的概念进行包装,请查看标准库中的Swing UI工具包(或AWT)。

Because you can imagine what can be visualized (e.g., a button, a label), it's easy to contrast it with the things that can't be instantiated (e.g., a JComponent).

因为您可以想象什么可以可视化(例如,一个按钮,一个标签),很容易将它与不能实例化的东西(例如,JComponent)进行对比。

#8


2  

An interface contains no implementation at all.

一个接口不包含任何实现。

An abstract class may contain some implementation, that is useful to all subclasses, but not be complete : it needs to be completed in some way in the subclasses.
Where the interface lets you use polymorphism on several classes, abstract class also lets them reuse code.

一个抽象类可能包含一些实现,它对所有子类都有用,但不完整:它需要在子类中以某种方式完成。如果接口允许您在多个类上使用多态性,那么抽象类还允许它们重用代码。

     public abstract class Figure {
        protected Point position;

        public abstract void draw();
     }

     public class Square extends Figure {
       // position is usable

       public void draw() {
         // this method must be implemented, for Square not to be abstract
       }

       // here is other code
     }

Another difference is that a class can only have one superclass, but implements many interfaces. This can be a limiting factor.

另一个区别是类只能有一个超类,但是实现了许多接口。这可能是一个限制因素。

#9


2  

You can restrict the order of execution of an instruction with specific steps, but allow delegation for the behavior of each step:

您可以通过特定的步骤限制指令的执行顺序,但是允许每个步骤的行为的授权:

public abstract class Instruction {

    void perform() {
        firstStep();
        secondStep();
        thirdStep();
    }

    abstract void firstStep();

    abstract void secondStep();

    abstract void thirdStep();

}

#10


1  

When and why should abstract classes be used?

何时以及为什么要使用抽象类?

Below post answers your query:

以下是您的查询:

Interface vs Abstract Class (general OO)

接口vs抽象类(通用OO)

I would like to see some practical examples of their uses.

我想看一些他们使用的实例。

When You want to share code among several closely related classes

当您想要在几个紧密相关的类*享代码时。

One practical example : Template method implementation in JDK Reader.java class

一个实际的例子:JDK阅读器中的模板方法实现。java类

Have a look at below post:

请看下面的帖子:

Template design pattern in JDK, could not find a method defining set of methods to be executed in order

在JDK中模板设计模式,无法找到一个方法来定义要按顺序执行的方法。

what is the difference between abstract classes and interfaces?

抽象类和接口的区别是什么?

Refer to this post:

请参考这篇文章:

How should I have explained the difference between an Interface and an Abstract class?

我应该如何解释接口和抽象类之间的区别?

#11


0  

In my own thinking, the correct way is to approach this question is to determine the context you are dealing with regarding the domain or entity objects first, namely what is your use case?

在我自己的想法中,正确的方法是解决这个问题,就是要确定你首先要处理的领域或实体对象的上下文,即你的用例是什么?

In my personal experience, I do this using a top down and then bottom up approach. I start looking for inheritance by looking at the use case and seeing what classes I will need. Then I look to see if there is a superClassOrInterfaceType (since both classes and interfaces define types, I'm combining them into a one word for simplicity. Hopefully it doesn't make it more confusing) domain object that would encompass all the objects, as in a superClassOrInterfaceType of vehicle if I'm working on a use case dealing with subtypeClassOrInterfaceTypes like: cars, trucks, jeeps, and motorcycles for example. If there is a hierarchy relationship, then I define the superClassOrInterfaceType and subtypeClassOrInterfaceTypes.

在我个人的经验中,我使用自上而下和自下而上的方法。通过查看用例并查看我需要的类,我开始寻找继承。然后,我想看看是否有超类orinterfacetype(因为类和接口都定义了类型,我将它们组合成一个简单的词)。希望它不会使它变得更加混乱)域对象,它将包含所有对象,就像在一个超classorinterfacetype of vehicle中,如果我在处理一个用例来处理像:汽车、卡车、吉普车和摩托车这样的子类型的类型。如果存在层次关系,那么我定义超类或子类型的类型。

As I said, what I generally do first is to look for a common domain superClassOrInterfaceType for the objects I'm dealing with. If so, I look for common method operations between the subtypeClassOrInterfaceTypes. If not, I look to see if there are common method implementations, because even though you may have a superClassOrInterfaceType and may have common methods, the implementations may not favor code reuse. At this point, if I have common methods, but no common implementations, I lean towards an interface. However, with this simplistic example, I should have some common methods with some common implementations between the vehicle subtypeClassOrInterfaceTypes that I can reuse code with.

正如我所说的,我通常首先要寻找的是我正在处理的对象的一个通用的域超classorinterfacetype。如果是这样,我将在子类型匹配类型之间寻找常见的方法操作。如果没有,我想看看是否有通用的方法实现,因为即使您可能有一个超类orinterfacetype,并且可能有通用的方法,但是实现可能不支持代码重用。在这一点上,如果我有通用的方法,但是没有通用的实现,我倾向于一个接口。但是,通过这个简单的示例,我应该有一些常见的方法,在汽车的子类型组合接口类型之间有一些常见的实现,我可以重用代码。

On the other hand, if there is no inheritance structure, then I start from the bottom up to see if there are common methods. If there are no common methods and no common implementations, then I opt for a concrete class.

另一方面,如果没有继承结构,那么我就从底部开始,看看是否有通用的方法。如果没有通用的方法,也没有通用的实现,那么我选择一个具体的类。

Generally, if there is inheritance with common methods and common implementations and a need for multiple subtype implementation methods in the same subtype, then I go with an abstract class, which is rare, but I do use it. If you just go with Abstract classes just because there is inheritance, you can run into problems if the code changes a lot. This is detailed very well in the example here: Interfaces vs Abstract Classes in Java, for the different types of domain objects of motors. One of them required a dual powered motor, that required multiple subtype implementation methods to be used in a single subtype class. In other words, a single class needed implementation methods from both solar powered and battery powered motors, which is modeling behaviors and not something you want to do with Abstract classes.

一般来说,如果在相同的子类型中有通用方法和通用实现的继承和对多个子类型实现方法的需求,那么我就会使用一个抽象类,这很少见,但是我确实使用了它。如果仅仅因为有继承而使用抽象类,那么如果代码更改很多,就会遇到问题。其中一个需要双动力马达,这需要在一个子类中使用多个子类型实现方法。换句话说,一个单独的类需要来自太阳能和电池驱动的马达的实现方法,它是建模行为,而不是你想要用抽象类做的事情。

To sum it all up, as a rule you want to define behaviors (what the objects will do) with interfaces and not in Abstract classes. Abstract classes focus on an implementation hierarchy and code reuse.

总的来说,作为一个规则,您希望定义行为(对象将做什么)与接口,而不是抽象类。抽象类关注于实现层次结构和代码重用。

Here are some links that go into greater details on this.

这里有一些关于这个的更详细的链接。

Thanks Type & Gentle Class

谢谢类型和温和的课程。

The Magic behind Subtype Polymorphism

子类型多态性背后的神奇。

Maximize Flexibility with Interfaces & Abstract Classes

最大化的灵活性与接口和抽象类。

Interfaces vs Abstract Classes in Java

接口与Java中的抽象类。