疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java面向对象之 抽象类


 

   

  (一)抽象类

  在某些情况下,某个父类只是知道其子类应该包含怎样的方法,但是无法准确地知道这些子类如何实现这些方法,可以选择定义抽象类。

  (二)抽象类和抽象方法

  抽象方法和抽象类必须使用abstract修饰符来定义,有抽象方法的类只能被定义成抽象类,抽象类里可以没有抽象方法。

  抽象方法和抽象类的规则如下:

  (1)抽象类必须使用abstract修饰符来修饰,抽象方法也必须使用abstract修饰符来修饰,抽象方法不能有方法体。

  (2)抽象类不能被实例化,无法使用new关键字调用抽象类的构造器创建抽象类的实例。即使抽象类里不包含抽象方法,这个抽象类也不能创建实例。

  (3)抽象类可以包含Field、方法(普通方法和抽象方法都可以)、构造器、初始化块、内部类、枚举类6种成分。抽象类的构造器不能用于创建实例,主要是用于被其子类调用。

  (4)含有抽象方法的类 只能被定义成抽象类。

  下面定义一个抽象类:

  复制代码

  package Chapter6;

  public abstract class Shape

  {

  {

  System.out.println("执行Shape的初始化块...");

  }

  private String color;

  //定义一个计算周长的抽象方法

  public abstract double calPerimeter();

  //定义一个饭盒形状的抽象方法

  public abstract String getType();

  //定义一个Shape的构造器,该构造器并不是用于创建Shape对象

  //而是用于被子类调用

  public Shape()

  {

  }

  public Shape(String color)

  {

  System.out.println("执行Shape的构造函数");

  this.color = color;

  }

  public String getColor()

  {

  return color;

  }

  public void setColor(String color)

  {

  this.color = color;

  }

  }

  复制代码

  复制代码

  package Chapter6;

  public class Triangle extends Shape

  {

  //定义三角形的三边

  private double a;

  private double b;

  private double c;

  public Triangle(String color,double a,double b,double c)

  {

  super(color);

  setSides(a,b,c);

  }

  public void setSides(double a,double b,double c)

  {

  if(a >= b+c || b >= a + c || c >= a + b)

  {

  System.out.println("三角形两边之和必须大于第三边");

  return;

  }

  this.a = a;

  this.b = b;

  this.c = c;

  }

  /**

  * 功能:

  * 计算三角形周长

  */

  @Override

  public double calPerimeter()

  {

  return a + b + c;

  }

  @Override

  public String getType()

  {

  return "三角形";

  }

  }

  复制代码

  复制代码

  package Chapter6;

  public class Circle extends Shape

  {

  private double radius;

  public Circle(String color,double radius)

  {

  super(color);

  this.radius = radius;

  }

  public void setRadius(double radius)

  {

  this.radius = radius;

  }

  /**

  * 功能:

  * 重新计算园的周长

  */

  @Override

  public double calPerimeter()

  {

  return 2 * Math.PI + radius;

  }

  @Override

  public String getType()

  {

  return getColor() +"圆形";

  }

  }

  复制代码

  复制代码

  package Chapter6;

  public class TestShape

  {

  public static void main(String[] args)

  {

  Shape s1 = new Triangle("黑色",3,4,5);

  Shape s2 = new Circle("黄色",3);

  System.out.println(s1.getType());

  System.out.println(s1.calPerimeter());

  System.out.println(s2.getType());

  System.out.println(s2.calPerimeter());

  }

  }

  复制代码

  运行结果:

  复制代码

  执行Shape的初始化块...

  执行Shape的构造函数

  执行Shape的初始化块...

  执行Shape的构造函数

  三角形

  12.0

  黄色圆形

  9.283185307179586

  复制代码

  (注意:abstract不能用于修饰Field,不能用于修饰局部变量,即没有抽象变量、没有抽象Field等说法;abstract也不能用于修饰构造器,没有抽象构造器,抽象类里定义的构造器只能是普通构造器)

  当使用static修饰一个方法时,表明这个方法属于该类本身,即通过类就可调用该方法,但如果该方法定义成抽象方法,则将导致通过该类调用该方法时出现错误(调用一个没有方法体的方法肯定会引起错误)。因此static和abstract不能同时修饰某个方法,即没有所谓的类抽象方法。

  (二)抽象类的作用

  抽象类不能创建实例,只能当成父类来呗继承。抽象类体现的就是一种模板模式的设计,抽象类作为多个子类的通用模板,子类在抽象类的基础上进行扩展、改造,但子类总体上会大致保留抽象类的行为方式。

  如果编写一个抽象父类,父类提供了多个子类的通用方法,并把一个或多个方法留给其子类实现,这就是一种模板模式,模板模式也是十分常见且简单的设计模式之一。

  模板模式在面向对象的软件中很常用,其原理简单,实现也很简单。下面是使用模板模式的一些简单规则:

  (1)抽象父类可以只定义需要使用的某些方法,把不能实现的部分抽象成抽象方法,留给其子类去实现。

  (2)父类中可能包含需要调用的其他系列方法的方法,这些被调方法既可以由父类实现,也可以由其子类实现。父类里提供的方法只是定义了一个通用算法,其实现也许并不完全由自身实现,而必须依赖于其子类的辅助。