如何以及何时使用抽象类?

38

这是我的Java测试程序。我想知道在这里抽象类有多重要,以及为什么我们要使用抽象类。

这是一种强制性方法还是最佳做法;如果是的话,怎么做?

class Shape1 {
    int i = 1;
    void draw() {
        System.out.println("this is shape:" + i);
    }
}

class Shape2 {
    int i = 4;
    void draw() {
        System.out.println("this is shape2:" + i);
    }
}


class Shape {
    public static void main(String args[]) {
        Shape1 s1 = new Shape1();
        s1.draw();

        Shape2 s2 = new Shape2();
        s2.draw();
    }
}

2
我认为你的例子更适合使用接口而不是抽象类。这是展示接口用法的典型例子之一:可以绘制不同形状(正方形、圆形等)。 - PeterMmm
6个回答

22

你需要在这里使用一个抽象类或接口,以创建一个通用的基类/接口,提供void draw()方法,例如:

abstract class Shape() {
  void draw();
}

class Circle extends Shape {
   void draw() { ... }
}

...

Shape s = new Circle();
s.draw();

通常我会使用接口。但是如果:

  1. 您需要/想要提供公共功能或类成员(例如您的情况下的int i成员)。
  2. 您的抽象方法具有除公共访问之外的任何其他访问权限(这是接口允许的唯一访问类型),例如在我的示例中,void draw()将具有包可见性。

6

抽象类是至少有一个未实现方法或关键字abstract的类。例如,抽象方法可能如下所示:

public abstract String myMethod(String input);

(注意方法以分号结尾)。

一个类可能如下所示:

public abstract class MyClass {

    public abstract String myMethod(String input);

    public String anotherMethod(String input) {
        return intput + " additional text";
    }
}

抽象类不能被实例化。需要子类实现缺失的行为才能实例化抽象类。

抽象类的主要目的是提供共享的通用行为实现,促进代码重用。

在Java中,可以通过使用类的组合而不是继承广义定义的抽象类来实现相同的效果。这样可以创建更多模块化、功能特定的类,促进代码重用,从而提高可维护性。

我的建议是只在严格必要的情况下使用抽象类,特别是避免将其用作包含各种功能的“魔法包”。

在Scala中,traits是解决这个问题的一种优雅方式。但是,需要非常注意才能正确使用。

编辑:从Java 8开始,接口中的默认方法是添加通用行为的另一种方式。


1
抽象类不一定需要有抽象方法...例如,您可以定义一个所有方法都已实现的抽象类。 - Alex Lockwood

5
一个抽象类与它的子类之间具有“is-a”的类型关系。例如,你可以有一个抽象类Shape,它拥有任何形状都有的东西(比如绘制函数),然后有一个类SquareShape。每个SquareShape都是一个Shape,但不是所有的Shape都是SquareShape。
在你的例子中,你有2种形状类型和一个包含这些实例的类。我认为这不是你应该用abstract定义的关系。
你可能需要对你的名称做一些处理,因为这只是一个相当简单的例子,很难看出文件的真正含义以及它们应该如何工作。

5

常见的事情 + 不寻常的事情 = 抽象类

何时使用?

当有大量可重复使用的代码,并且您不想反复编写时,抽象类最适合使用 + 有一些特定于每个类的东西。

例如?

典礼:

共同的事情: 唱国歌,升旗等
特定的事情: 印度国旗、印度国歌(对于印度)、中国国旗、中国国歌(对于中国)等。

enter image description here

如何使用?

1) 创建一个抽象类
2) 将所有通用的内容放入公共方法中
3) 将所有特定于子类的内容放入抽象方法中

样例代码在哪里?

基类:

public abstract class BaseCeremony{

    Flag natonalFlag;
    Anthem anthem;

    //**** Common Task ******//
    public void startCeremony(){
        configure();
        hoistFlag();
        singAnthem();
    }

    public void hoistFlag(){
        natonalFlag.hoist();                       
    }

    public void singAnthem(){
        anthem.anthem();                       
    }

    private void configure(){
        natonalFlag = provideFlag();
        anthem = provideAnthem();
    }

    //**** Differs in all part ******//
    public abstract Flag provideFlag();
    public abstract Anthem provideAnthem();

}

在子类中,您只需要提供与父类不同的部分的实现。 ChildClass
public class IndianCeremony extends BaseCeremony{

       public Flag provideFlag(){
            return new IndianFlag();
       }

       public Anthem provideAnthem(){
            return new IndianAnthem();
       }
}

奖金


3

Java中使用抽象类的示例

package use_of_abstract;

abstract class Shapes 
{
   int i=1;

   abstract void draw();
   abstract void color(String mycolor);

   //not an abstract method
   void fill()
   {
      System.out.println("Non-Abstract Method -> Fill"); 
   }

   //not an abstract method
   String anotherMethod(String input) 
   {
       return input + " additional text";
   }

}

package use_of_abstract;

public class Shape_One extends Shapes 
{
    int i=1;

    @Override
    void draw() 
    {
        System.out.println("This is Shape One:"+i);
    }

    @Override
    void color(String mycolor) 
    {
        System.out.println("This is Shape One:"+mycolor);

    }

    @Override
    String anotherMethod(String anotherMethod) 
    {
        System.out.println("This is Shape One:"+anotherMethod);
        return anotherMethod;

    }

}

package use_of_abstract;

public class Shape_Two extends Shapes
{
    int i=2;

    @Override
    void draw() 
    {
        System.out.println("This is Shape Two :"+i);
    }

    @Override
    void color(String mycolor) 
    {
        System.out.println("This is Shape Two Color:"+mycolor);
    }

    @Override
    String anotherMethod(String anotherMethod) 
    {
        System.out.println("This is Shape Two:"+anotherMethod);
        return anotherMethod;

    }

}

package use_of_abstract;

import java.awt.Color;

public class Shape_Main 
{

    public static void main(String args[])
    {
        Shape_One s1;
        Shape_Two s2;

        s1=new Shape_One();
        s2= new Shape_Two();

        s1.draw();
        s2.draw();

        s1.fill();
        s2.fill();

        s1.color("Blue");
        s2.color("Green");


        s1.anotherMethod("HELLO..............Its Another Method 1");
        s2.anotherMethod("HELLO..............Its Another Method 2");


    }   
}

2
抽象类,顾名思义就是抽象的。
抽象类并不涉及实现部分。事实上,我们扩展抽象类以为其抽象方法提供实现。它也可以有非抽象方法。
在此处查看:Java中抽象类的用途 编辑:
示例代码:
abstract class Shapes {

 int i=1;
 abstract void draw(); 

 // Remember : Non-abstract methods are also allowed 
 void fill() {
     System.out.println("Non abstract method - fill");
 }
}

class Shape1 extends Shapes {

 int i=1;
 void draw(){
 System.out.println("This is Shape 1:"+i);
 }
}

class Shape2 extends Shapes {
    int i=2;
    void draw() {
        System.out.println("This is Shape 2:"+i);
    }
}

class Shape {

public static void main(String args[])
       {
        Shape1 s1 = new Shape1();
        s1.draw();                     // Prints This is Shape 1:1

        Shape2 s2 = new Shape2();
        s2.draw();                     // Prints This is Shape 2:2
       }
  }

2
这是不正确的。抽象类可以有大量的实现。它也可以有抽象方法,看起来需要扩展类来实现,但它肯定可以有实现。接口没有实现,抽象类可以有(是的,您可以拥有只有抽象方法的抽象类,但不一定非要这样)。当然,您不能拥有抽象类的实例。 - Nanne

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