java 抽象类的意义何在?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7728056/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 21:09:34  来源:igfitidea点击:

What is the point of an abstract class?

java

提问by Lews Therin

I understand what an abstract class is in OOP paradigm. Yeah an abstract class is an incomplete type, cannot be instantiated.

我了解 OOP 范式中的抽象类是什么。是的,抽象类是不完整的类型,无法实例化。

Subclasses of the abstract class can extend the superclass and so on, and call a method through using a base type variable. But that is what I don't get.

抽象类的子类可以扩展超类等,并通过使用基类型变量调用方法。但那是我不明白的。

I was reading the book, and the author said using a Superclass variable to reference a subclass and calling a common method calls the correctmethod. And yeah that's true. For example this little code I wrote:

我在看书,作者说使用Superclass变量引用子类,调用公共方法调用正确的方法。是的,这是真的。例如我写的这个小代码:

public class ObjectOne extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectOne\n" ;
    }
}



public class ObjectTwo extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectTwo\n" ;
    }
}


public class ObjectThree extends SuperObject {

    public String objectString()
    {
        return "objectString() of class ObjectThree\n" ;
    }
}


public class SuperObject {
    public String objectString()
    {
        return "SuperObject" ;      
    }
}

    import static java.lang.System.out ;
public class ControlClass {

    public static void main(String[] args)
    {
        SuperObject [] arr = {new ObjectOne(), new ObjectTwo(), new ObjectThree()} ;

        for(SuperObject elem:arr)
        {
            out.println(elem.objectString()) ;
        }
    }
}

Em, so when main executes the correctmethods are called for the objects using just the reference type. My question is so what is the point of an abstract class? Polymorphism works regardless of whether the method or class is abstract. Unlike C++, polymorphism works only whenyou specify it. For Java, it works apparently all the time.

Em,所以当 main 执行时,只使用引用类型为对象调用正确的方法。我的问题是抽象类的意义何在?无论方法或类是否是抽象的,多态都有效。与 C++ 不同,多态性仅您指定时才起作用。对于 Java,它显然一直有效。

So I guess the abstract keyword or abstract concept is just to complete the inheritance hierarchy, make incomplete types impossible to instantiate, or is to promote good OOP practice? Can someone clarify thanks.

所以我猜抽象关键字或抽象概念只是为了完成继承层次结构,使不完整的类型无法实例化,还是促进良好的 OOP 实践?谁能解释一下谢谢。

采纳答案by Jon

I'm not sure you understand what an abstract class is, as none of the classes in your example are abstract, and nothing in there is an interface either. What you are doing is extending an instantiable class. Without the abstractkeyword there is nothing to stop me doing:

我不确定您是否理解抽象类是什么,因为您的示例中没有一个类是抽象的,并且其中也没有任何接口。您正在做的是扩展一个可实例化的类。没有abstract关键字没有什么可以阻止我做:

SuperObject obj = new SuperObject();

SuperObject obj = new SuperObject();

I think a better example would be to illustrate how abstract classes are used. What they are commonly used to do is to provide a common method implementation. If a number of classes implement some interface, but all of them implement the same method in the same way using the same code, then what is commonly done is to create an abstractclass that contains the common implementation, and get all of the concrete implementations to extend that class. This facilitates code reuse, and decreases the likelihood that one developer will change the common method implementation for one class, but forget the others. For example..

我认为一个更好的例子是说明如何使用抽象类。它们通常用来做的是提供一个通用的方法实现。如果多个类实现了某个接口,但它们都使用相同的代码以相同的方式实现了相同的方法,那么通常所做的就是创建一个abstract包含公共实现的类,并获取所有具体实现扩展那个类。这有助于代码重用,并降低开发人员更改一个类的公共方法实现而忘记其他类的可能性。例如..

public class ObjectOne extends Thing {
  public String objectString()
  {
      return "objectString() of class ObjectOne\n" ;
  }
}

public class ObjectTwo extends Thing {
  public String objectString()
  {
    return "objectString() of class ObjectTwo\n" ;
  }
}

public class ObjectThree extends Thing {
  public String objectString()
  {
    return "objectString() of class ObjectThree\n" ;
  }
}

public abstract class Thing implements SuperObject {
  public String alwaysTheSame() {
    return "The same thing";
  }
}

public interface SuperObject {
  public String objectString();

  public String alwaysTheSame();
}

import static java.lang.System.out ;

public class ControlClass {

  public static void main(String[] args)
  {
    SuperObject [] arr = {new ObjectOne(), new ObjectTwo(), new ObjectThree()} ;

    for(SuperObject elem : arr)
    {
        out.println(elem.alwaysTheSame());
        out.println(elem.objectString()) ;
    }
  }
}

What we have done here is introduce an abstractclass Thing, which provides a method implementation that is common to all 3 implementations of SuperObject(which is now an interface). This means we don't have to write the same code again in three different places in order to to fully implement the SuperObjectinterface in each one of our concrete classes.

我们在这里所做的是引入一个abstractclass Thing,它提供了一个方法实现,该方法实现对所有 3 个实现SuperObject(现在是一个接口)是通用的。这意味着我们不必在三个不同的地方再次编写相同的代码,以便SuperObject在我们的每个具体类中完全实现接口。

In addition to this, you can also extendnon finalclasses. You may wish to do this in order to override the default behaviour of one or methods on the concrete class, or to decorate the the class with additional methods. Of course, when you are designing a class hierarchy from scratch you don't stick concrete classes in it that then get extended by other classes, as it's generally considered a bad code smell. However, few of us work with totally new written-from-scratch codebases, and must adapt an exiting codebase to new requirements. Extending a concrete class is one tool in the toolbox to do this.

除此之外,您还可以extendfinal类。您可能希望这样做是为了覆盖具体类上的一个或多个方法的默认行为,或者用其他方法装饰该类。当然,当您从头开始设计类层次结构时,您不会将具体类粘贴在其中然后由其他类扩展,因为它通常被认为是一种糟糕的代码气味。然而,我们中很少有人使用全新的从头开始编写的代码库,并且必须使现有的代码库适应新的需求。扩展一个具体的类是工具箱中的一个工具来做到这一点。

EDIT: Misunderstood what the OP was asking, but the last paragraph above is relevant.

编辑:误解了 OP 的要求,但上面的最后一段是相关的。

回答by Saket

Abstract classes are an excellent way to create planned inheritance hierarchies. They're also a good choice for nonleaf classes in class hierarchies.

抽象类是创建计划继承层次结构的绝佳方式。对于类层次结构中的非叶类,它们也是一个不错的选择。

Here's a good detailed explanation:(extracted from here)

这是一个很好的详细解释:(这里提取)

Choosing interfaces and abstract classes is not an either/or proposition. If you need to change your design, make it an interface. However, you may have abstract classes that provide some default behavior. Abstract classes are excellent candidates inside of application frameworks.

Abstract classes let you define some behaviors; they force your subclasses to provide others. For example, if you have an application framework, an abstract class may provide default services such as event and message handling. Those services allow your application to plug in to your application framework. However, there is some application-specific functionality that only your application can perform. Such functionality might include startup and shutdown tasks, which are often application-dependent. So instead of trying to define that behavior itself, the abstract base class can declare abstract shutdown and startup methods. The base class knows that it needs those methods, but an abstract class lets your class admit that it doesn't know how to perform those actions; it only knows that it must initiate the actions. When it is time to start up, the abstract class can call the startup method. When the base class calls this method, Java calls the method defined by the child class.

选择接口和抽象类不是一个非此即彼的命题。如果您需要更改设计,请将其设为界面。但是,您可能有提供某些默认行为的抽象类。抽象类是应用程序框架内的优秀候选者。

抽象类让你定义一些行为;他们强迫你的子类提供其他的。例如,如果您有一个应用程序框架,一个抽象类可能会提供默认服务,例如事件和消息处理。这些服务允许您的应用程序插入到您的应用程序框架中。但是,有一些特定于应用程序的功能只有您的应用程序才能执行。此类功能可能包括启动和关闭任务,这些任务通常依赖于应用程序。因此,抽象基类可以声明抽象的关闭和启动方法,而不是尝试定义该行为本身。基类知道它需要这些方法,但是抽象类让您的类承认它不知道如何执行这些操作;它只知道它必须发起行动。该启动的时候,抽象类可以调用启动方法。当基类调用该方法时,Java 调用子类定义的方法。

回答by MasterCassim

You also don't have to implement certain methods in abstract classes. You can decide what have to be declared in Subclasses and what you want declare in the Superclass.

您也不必在抽象类中实现某些方法。您可以决定必须在子类中声明什么以及要在超类中声明什么。

Look at OutputStream for example:

以输出流为例:

public abstract void write(int i) throws IOException;

public void write(byte abyte0[]) throws IOException {
    write(abyte0, 0, abyte0.length);
}

public void write(byte abyte0[], int i, int j) throws IOException {
    if(abyte0 == null)
        throw new NullPointerException();
    if(i < 0 || i > abyte0.length || j < 0 || i + j > abyte0.length || i + j < 0)
        throw new IndexOutOfBoundsException();
    if(j == 0)
        return;
    for(int k = 0; k < j; k++)
        write(abyte0[i + k]);
}

You have an abstract write method (because you don't knwo where the OutputStream is going to) but all other extra write methods are not abstract and forwarded to this methods. So you only have to declare one method in the Subclass and have some methods "extra" without having to implement it in every Subclass.

您有一个抽象的 write 方法(因为您不知道 OutputStream 要去哪里),但所有其他额外的 write 方法都不是抽象的并转发到此方法。所以你只需要在子类中声明一个方法,并有一些“额外”的方法,而不必在每个子类中实现它。

回答by Nicolas Zozol

Let's say you want to deploy an application on an Ipad, Android, Iphoneand Desktopapplication. You work on an important part that will do 95% of the job in an abstract class. Then you create 4 other small classes that will implement the abstract method differently for each device.

假设您想在IpadAndroidIphone桌面应用程序上部署一个应用程序。您在一个重要的部分工作,它将在抽象类中完成95% 的工作。然后创建 4 个其他小类,它们将为每个设备以不同的方式实现抽象方法。

That way, you won't repeat 95% of the work, and each device will instanciate his own class, that extends the abstract common class.

这样,你就不会重复 95% 的工作,每个设备都会实例化自己的类,扩展抽象的公共类。

回答by hevi

You may want a class not to have any instances. For example assume you have a Person class and two classes derived from it Student and Teacher. In this case you may not want to have any objects created from Person class as it may not have any meaning for your program.

您可能希望一个类没有任何实例。例如,假设您有一个 Person 类和从它派生的两个类 Student 和 Teacher。在这种情况下,您可能不希望从 Person 类创建任何对象,因为它可能对您的程序没有任何意义。

回答by Dave Newton

The "point" is to enforce a class hierarchy, potentially with some functionality provided by base class(es), and force some behavior to be implemented by sub-classes.

“要点”是强制执行类层次结构,可能具有基类提供的某些功能,并强制子类实现某些行为。

回答by Alexander Rühl

You would use an abstract class in cases where you dowant to specify certain behaviour but don'twant anybody to instatiate it directly but having to subclass it.

如果您确实想要指定某些行为但希望任何人直接对其进行实例化而必须对其进行子类化,则可以使用抽象类。

回答by gotomanners

An abstract class can be full bodied or the skeleton for the subclass. You define your template in the abstract class and its left for the subclass to extend and implement the methods defined in the superclass.

抽象类可以是完整的,也可以是子类的骨架。您在抽象类中定义模板,并在其左侧为子类扩展和实现超类中定义的方法。

回答by michael667

So I guess the abstract keyword or abstract concept is just to complete the inheritance hierarchy, make incomplete types impossible to instantiate, or is to promote good OOP practice?

所以我猜抽象关键字或抽象概念只是为了完成继承层次结构,使不完整的类型无法实例化,还是促进良好的 OOP 实践?

My answer is yesto everything that you said.

你说的一切都是肯定的

回答by Bradley Uffner

Along with what others have said, you may be using a library written by someone else, where you don't have access to the source code, but want to change it's behavior.

与其他人所说的一样,您可能正在使用其他人编写的库,您无法访问源代码,但想要更改其行为。