抽象类
抽象类的定义
- 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类。
- 抽象类除了不能实例化对象之外,类的其它功能依然存在,成员变量、成员方法和构造方法的访问方式和普通类一样。
- 由于抽象类不能实例化对象,所以抽象类必须被继承,才能被使用。也是因为这个原因,通常在设计阶段决定要不要设计抽象类。
- 父类包含了子类集合的常见的方法,但是由于父类本身是抽象的,所以不能使用这些方法。
- 在 Java 中抽象类表示的是一种继承关系,一个类只能继承一个抽象类,而一个类却可以实现多个接口。
抽象类的举例
形状类Shape需要提供用于计算面积和周长的方法,但是形状本身没有被确定,那么计算周长和面积的方法就无法确定,此时我们就需要使用抽象类和抽象方法。
由于Shape类计算周长和面积的方法无法确定,那么就可以将这样的方法声明为抽象的,以便在具体的子类中进行实现。
抽象类的声明
如果一个类的某些功能比较抽象或者无法在本类中具体实现,可以将这个类声明为抽象的,那么这些抽象或者无法具体实现的功能可以在子类中完成。
抽象类的语法
[修饰符] abstract class 类名 [extends 父类名]{类体}
- 抽象类和普通类除了使用abstract修饰外和普通的类相似
- 抽象类中可以没有抽象方法
- 但是一旦某个有抽象方法,那么这个类必须被声明为抽象类
注意:[ ]可以不写。
抽象方法的声明
[修饰符] abstract 返回值类型 方法名([参数列表]);
注意:因为抽象方法无法确定具体执行的功能,所有抽象方法没有方法体,需要在小括号后加上分号
代码示例
public abstract class Shape { //求面积的抽象方法 public abstract double area(); //求周长的抽象方法 public abstract double girth(); }
因为抽象类不是一个具体的类,所以无法实例化,但是抽象类可以用于声明对象
代码示例
public class ShapeTest { public static void main(String[] args) { //可以声明 Shape shape; //无法实例对象,这样写会报错 Shape shape1=new Shape(); //需要实现抽象类的抽象方法,才能实例化 Shape shape2=new Shape() { @Override public double area() { return 0; } @Override public double girth() { return 0; } }; } }
抽象类可以被继承,在子类中实现抽象类的所有抽象方法,以达到抽象类的具体化
代码示例
public class Circle extends Shape{ //半径变量 private double r; //有参构造器 public Circle(double r) { this.r = r; } //圆周率常量 private final static double PI=3.14; //重写求面积方法 @Override public double area() { return r*r*PI; } //重写求周长方法 @Override public double girth() { return 2*r*PI; } }
具体化后的子类方法就可以用来创建对象了
代码示例
public class ShapeTest { public static void main(String[] args) { //可以实例化一个半径为4的Shape的子类对象 Shape shape=new Circle(4); System.out.println("圆形的面积为 "+shape.area()); System.out.println("圆形的面积为 "+shape.girth()); } }
接口
在软件工程中,经常将一个大的项目分由不同的开发小组共同开发,各个小组的开发工作是并行的。在很多时候,对于不同小组的程序员来说,清楚地说明各自的软件如何相互作用,并就此达成统一“约定”是很重要的。这种情况下,每一小组都可以在对其他小组怎么编写代码一无所知的情况下,就能编写自己的代码,并且各自小组编写的代码能很好的协同工作。接口就是这样的“约定”。
接口的定义
在Java中接口不仅仅是程序开发过程中“约定”,更是更加抽象化的抽象类
接口的语法
[修饰符] interface 接口名{[常量];[抽象方法];}
public interface MyInterFace { public final static double PI=3.14; public abstract double area(); //变量声明不写默认就有 public final static double PI1=3.14; //方法声明不写默认就有 public abstract double area1(); }
接口的实现
定义类时通过implements关键字实现接口
接口实现的语法
[修饰符] class 类名 [extends 父类名] [implements 接口1,接口2,……]{类体部分}
代码示例
public class MyClass implements MyInterFace{ @Override public double area() { //具体实现。。。 return 0; } @Override public double area1() { //具体实现。。。 return 0; } }
注意:接口中只能有常量或者抽象方法
一个类可以实现多个接口,从而解决了Java单继承的缺点。
代码示例
public interface InterfaceA { void methodA(); }
public interface InterfaceB { void methodB(); }
public class MyClass implements InterfaceA,InterfaceB{ @Override public void methodA() { System.out.println("方法A"); } @Override public void methodB() { System.out.println("方法B"); } }
接口的继承
在Java中类之间的继承关系是单继承,也就是说一个类有且只能有一个父类。
而Java中的接口实现了多继承,也就是说一个接口可以有多个父接口。
代码示例
//接口可以继承接口,且可以同时继承多个 public interface InterfaceC extends InterfaceA,InterfaceB{ }
接口的作用
- 提高程序的重用性
- 提高程序的可扩展性
- 降低程序的耦合度
- 实现了多继承
编辑
编辑
作业
作业一:
设计一个台灯类Lamp其中台灯有灯泡这个属性,还有开灯(on)这个方法,设计一个灯泡类 其中有红灯泡(RedBuble) 和 绿灯泡(GreenBuble) 他们都有一个发亮的方法,请设计出一段代码可以使台灯开启灯泡发亮,并且保证替换不同种类的灯泡台灯类代码不被修改。
作业二:
设计一个继承关系其中存在动物类Animal、狗类Dog和猫类Cat,对于猫类和狗类都有一个吃eat方法,但是猫和狗的吃eat方法的实现不同,请合理的设计出Animal Dog Cat这3个类关系
作业三:
设计一个形状类(接口)Shape,方法:求周长和求面积
形状类(接口)的子类(实现类):Rect(矩形),Circle(圆形)
Rect类的子类:Square(正方形)
不同的子类会有不同的计算周长和面积的方法
创建三个不同的形状对象,放在Shape类型的数组里,分别打印出每个对象的周长和面积
作业四:
某公司的雇员分为以下若干类:
Employee:这是所有员工总的父类,属性:员工的姓名,员工的生日月份。方法:double getSalary(int month) 根据参数月份来确定工资,如果该月员工过生日,则公司会额外奖励100元。
SalariedEmployee:Employee的子类,拿固定工资的员工。属性:月薪
HourlyEmployee:Employee的子类,按小时拿工资的员工,每月工作超出160小时的部分按照1.5倍工资发放。属性:每小时的工资、每月工作的小时数
SalesEmployee:Employee的子类,销售人员,工资由月销售额和提成率决定。属性:月销售额、提成率
BasePlusSalesEmployee:SalesEmployee的子类,有固定底薪的销售人员,工资由底薪加上销售提成部分。属性:底薪。
写一个程序,把若干各种类型的员工放在一个Employee数组里,写一个方法,打印出某月每个员工的工资数额。注意:要求把每个类都做成完全封装,不允许非私有化属性。