什么时候需要使用抽象类?

时间:2014-07-30 04:34:01

标签: java oop subclass abstract

我对Java很新,但还不需要使用抽象类。我理解:

  • 抽象类无法实例化
  • 抽象类通常有抽象方法
  • 其目的仅限于扩展其他类

我也理解,当您想要创建组件的新版本时,可以使用抽象类。这是如何工作的?

在什么类型的(特定)情况下使用抽象类是有益的?

此外,我已经读过您可以使用它们来部分实现您的课程。"这究竟是什么意思?

我的最后一个问题是,是否可以扩展普通班级达到类似的结果?

6 个答案:

答案 0 :(得分:2)

  

在什么类型的(特定)情况下使用抽象类是有益的?

当你想在基类中提供一些预定义的方法而不允许用户实例化基类时,你会想要使用抽象类,因为只有更具体的子类定义了其余的行为是足够好的类来支持单独使用。

  

此外,我已经读过您可以使用它们来部分实现您的课程。"这究竟是什么意思?

这意味着如果你只需要声明方法(将它们标记为抽象),子类必须定义它们,同时还能够在抽象类中定义所有子类也可以使用的方法。

  

我的最后一个问题是,是否可以扩展普通班级达到类似的结果?

仅当基类的对象可以单独使用时。

答案 1 :(得分:1)

当您的部分功能已知时,您使用抽象类,但部分是可变的。

public abstract class Channel {

  private Response response;

  public abstract void connect();

  public abstract void sendMessage(Message message);

  public abstract Response awaitResponse();

  public abstract void disconnect();

  public void send(Message message) {
    connect();
    sendMessage(message);
    response = awaitResponse();
    disconnect();
  }

  public Response getResponse() {
    return response;
  }

}

现在你有一个"通讯渠道"您知道可以发送消息,但绝对不知道协议是什么,它如何连接,或者它如何处理响应。

举一个可以扭曲这个想法的例子。让我们探索"电子邮件"信道。

public class EmailChannel extends Channel {

  public void connect() {
    ... open a SMTP socket to the email server ...
    ... open a HTTP socket for the response channel ...
  }

  public void sendMessage(Message message) {
    ... create a URL with encoding for the "response link" ...
    ... negotiate SMTP protocol ELHO, etc...
    ... send an email message with the "message" contents ...
    ... append the embedded HTTP "response link" ...
    ... close the SMTP socket ...
  }

  public Response awaitResponse() {
    ... wait till expected "GET" occurs on the HTTP socket ...
    ... return new Response(... details ...)
  }

  public void disconnect() {
    ... close the HTTP socket ...
  }
}

上面的代码当然存在很多实际问题,但它是模板模式的一个例子,也是人们为什么要编写抽象类的一个很好的例子。

当您有更多实现时,抽象类变得更有价值。为了进一步扩展我们的slapdash示例,想象一个提供协议选择的系统。

Contact "John Doe" by
1) email
2) SMS
3) chat

将由

支持
public Channel getChannelForInput(int value) {
  switch (value) {
    case 1: return new EmailChannel();
    case 2: return new SMSChannel();
    case 3: return new ChatChannel();
    default: throw new IllegalArgumentException("value cannot be " + value);
  }
}

并且支持将适合类似

的内容
...
Channel channel = getChannelForInput(value);
channel.send(message);
displayResponse(channel.getResponse());
...

希望现在您可以看到如何保留某些行为,同时保留一些未指定的细节。

答案 2 :(得分:0)

向@NESPowerGlove解释添加示例。

想想这种情况,您有一个DAL(数据访问层),在所有DAO实现类中,您可能会重复执行某些操作,例如,打开连接,关闭连接,记录特定任务。 所以这些是你可以在抽象类中定义的操作(即BaseDAO) 现在每个扩展BaseDAO的DAOImpl只需要调用抽象类中定义的方法,用于打开关闭连接和记录...

这是一个非常具体的场景,你也可以在其他地方找到它的用法

答案 3 :(得分:0)

我认为阅读Abstract Classesthis link can help you

由于@NESPowerGlove已经回答了你的一些问题,所以我的答案仅包括示例,如果你愿意,我会添加细节。

将自己视为披萨公司的所有者(以及敏锐的程序员:p)。现在你在两个不同的国家有两个分支机构,比如美国和意大利。 既然您知道这两个国家的人都有different tastes,那么您就是customizing the pizza making process as per country's people taste。这意味着。美国分公司将按照美国风格供应比萨饼,意大利分店将供应意大利风格的比萨饼。

由于制作披萨在两个过程中都很常见,所以你用抽象方法`makePizza()'定义一个抽象类,方法被标记为抽象,因为你只知道分支会制作披萨,但是他们如何制作比萨饼是分支。

abstract class MyPizzaCompany{
  public asbtract void makePizza();
}

由于美国分公司提供美国风格的披萨,因此USBrach课程将自己实施(这里制作披萨的过程)来制作披萨。

class USBranch extends MyPizzaCompany{
    @Override
    void makePizza() {
        // make pizza in US style
    }
}

同样,意大利分公司

class ItalianBranch extends MyPizzaCompany{
    @Override
    void makePizza() {
        // make pizza in italian style
    }
}

答案 4 :(得分:0)

想象一下你正在写一堂课的场景。您将逻辑编写到当时已知的方法中,并声明几个方法抽象,其逻辑将由子类添加。

答案 5 :(得分:0)

当我们有以下要求时,我们应该创建抽象类

  1. 您希望为所有子类提供一些通用功能
  2. 根据不同的要求,每个子类必须有一些实现
  3. 您希望在具有抽象类对象引用的子类型之间进行处理。 (多态性)