抽象类
当父类的某些方法,需要声明,但是又不确定如何实现时,可以将其声明为抽象方法,那么这个类就是抽象类,用 abstract修饰的方法就是抽象方法,用 abstract修饰的类就是抽象类
package abstract_;
public class Abstract01 {
}
abstract class Animal{
private String name;
public Animal(String name) {
this.name = name;
}
//eat()方法实现了,但是因为不知道是什么动物,无法确定是吃那种食物,所有没有意义
//父类方法不确定性的问题
//将方法设计为抽象(abstract)方法,
//抽象方法:没有实现的方法-->没有实现:就是没有方法体
//当一个类中存在抽象方法时,需要将该类声明为抽象(abstract)类
// public void eat(){
// System.out.println("动物类,但是不知道什么动物,不知到吃什么");
// }
public abstract void eat();
}
一般来说,抽象类会被继承,由其子类来实现抽象方法
介绍
1、用 abstract关键字来修饰一个类时,这个类就叫抽象类
访问修饰符 abstract 类名{
}
2、用 abstract关键字修饰一个方法时,这个方法就是抽象方法
访问修饰符 abstract 返回类型 方法名 (参数列表);//没有方法体
3、抽象类的价值更多在于设计,是设计者设计好之后,让子类继承并实现抽象类
抽象类的使用注意事项和细节:
1、抽象类不能被实例化
2、抽象类不一定要包含 abstract修饰的方法,抽象类可以没有 abstract修饰的方法
3、一旦类包含了 abstract修饰的方法,则这个类必须声明 abstract
4、 abstract只能修饰类和方法,不能修饰属性和其他的
package abstract_;
public class AbstractDeta01 {
public static void main(String[] args) {
//1、抽象类不能被实例化
// A a = new A();//'A' 为 abstract;无法实例化
}
}
abstract class A{
//2、抽象类不一定要包含 abstract修饰的方法,抽象类可以没有 abstract修饰的方法
//还可以有实现的方法
public void hi(){
System.out.println("hi");
}
}
class B{//类 "B" 必须声明为抽象,或为实现 "B" 中的抽象方法 "hi()"
//3、一旦类包含了 abstract修饰的方法,则这个类必须声明 abstract
public abstract void hi();//非 abstract 类中存在 abstract 方法
}
class C{
//4、 abstract只能修饰类和方法,不能修饰属性和其他的
public abstract int n=1;//此处不允许使用修饰符 'abstract'
}
5、抽象类可以有任意成员(因为抽象类本质还是类),比如非抽象方法,构造器,静态属性等等
package abstract_;
public class aAbstractData01 {
public static void main(String[] args) {
System.out.println("你好");
}
}
abstract class D{
public int n1=100;//普通属性
private static String name="ccc";//静态属性
public void hi(){//普通方法
System.out.println("hi");
}
public abstract void hello();//抽象方法
public static void ok(){//静态方法
System.out.println("hello");
}
public D() {//构造器
}
}
6、抽象方法不能有主体(方法体),即不能实现
public abstract void hello();
7、如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为抽象类
abstract class E{
public abstract void hi();
}
abstract class F extends E{
}
class G extends E{
@Override
public void hi() {
System.out.println();//这里相当于G子类实现了父类E的抽象方法,所谓实现就是有方法体
}
}
8、抽象方法不能使用private final 和static修饰,因为抽象方法最终需要被子类重写(实现),但是这些关键字都和重写相违背
package abstract_;
public class aAbstractData02 {
}
abstract class A{
public final abstract void hi();
//非法的修饰符组合: 'abstract' 和'private'
//非法的修饰符组合: 'abstract' 和'static'
//非法的修饰符组合: 'abstract' 和'final'
}
static 静态的 随着类加载而执行,并且只会执行一次
final 最终的,不能被继承
private 私有的,只有该类能够访问
习题
1、编写一个Employee类,声明为抽象类,包含以下三个属性,name ,id ,salary。提供必要的构造器和抽象方法work(),对于Manager类,它既是员工,还有奖金(bonus)属性。使用继承思想,设计CommonEmployee类和Manager类,要求类中提供必要的方法进行属性访问,实现work(),提示经理/普通员工 名字 工作中, oop的继承+抽象类
package abstract_;
public class AbstractExercise01 {
public static void main(String[] args) {
//测试
Manager em01 = new Manager("张三", 1, 10000,8000);
em01.work();
CommonEmployee em02 = new CommonEmployee("李四", 2, 5000);
em02.work();
}
}
abstract class Employee{
private String name;
private int id;
private double salary;
public Employee(String name, int id, double salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public abstract void work();//抽象方法
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
}
//如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为抽象类
class Manager extends Employee{
private double bonus;
public Manager(String name, int id, double salary, double bonus) {
super(name, id, salary);
this.bonus = bonus;
}
public double getBonus() {
return bonus;
}
public void setBonus(double bonus) {
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("经理"+getName()+"工作中");
}
}
如果一个类继承了抽象类,则它必须实现抽象类的所有抽象方法,除非它自己也声明为抽象类
class CommonEmployee extends Employee{
public CommonEmployee(String name, int id, double salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("员工"+getName()+"工作中");
}
}
2、有多个类,完成不同的任务job,要求统计各自完成任务的时间
普通写法
package abstract_;
public class BB {
public static void main(String[] args) {
BB bb = new BB();
bb.job();
}
public void job(){
int num=0;
long start=System.currentTimeMillis();
for (int i = 1; i <= 100000000; i++) {
num+=i;
}
long end=System.currentTimeMillis();
System.out.println("BB经过的时间"+(end-start));
}
}
package abstract_;
public class AA {
public static void main(String[] args) {
AA aa = new AA();
aa.job();
}
public void job(){
int num=0;
long start=System.currentTimeMillis();
for (int i = 1; i <= 100000000; i++) {
num+=i;
}
long end=System.currentTimeMillis();
System.out.println("AA经过的时间"+(end-start));
}
}
改进一--->如果需要增加更多的job方法,那么可以把复用的代码提取出来写一个新的方法,实现代码的复用,让代码更加简洁
package abstract_.Work_;
public class TestTemplate {
public static void main(String[] args) {
AA aa = new AA();
aa.Emp();
BB bb = new BB();
bb.Emp();
}
}
class AA{
public void job(){
int num = 0;
for (int i = 1; i <= 100000000; i++) {
num+=i;
}
}
public void Emp(){
long start=System.currentTimeMillis();
job();
//job1();
//job2();
//......
long end=System.currentTimeMillis();
System.out.println("AA经过的时间"+(end-start));
}
}
class BB{
public void job(){
int num = 0;
for (int i = 1; i <= 100000000; i++) {
num+=i;
}
}
public void Emp(){
long start=System.currentTimeMillis();
job();
//job1();
//job2();
//......
long end=System.currentTimeMillis();
System.out.println("BB经过的时间"+(end-start));
}
}
最终改进-->抽象模板设计模式-->多态--->动态绑定机制---具体执行情况使用debug查看
package abstract_.Work_;
public class Test{
public static void main(String[] args) {
A a = new A();
a.calculateTime();
B b = new B();
b.calculateTime();
}
}
abstract class Template {//抽象类。模板设计模式
public abstract void job();//抽象方法
public void calculateTime(){
//得到开始的时间
long start = System.currentTimeMillis();
job();//动态绑定机制
long end = System.currentTimeMillis();
System.out.println("执行时间"+(end-start));
}
}
class A extends Template{
@Override
public void job() {
int num = 0;
for (int i = 1; i <= 100000000; i++) {
num+=i;
}
}
}
class B extends Template{
@Override
public void job() {
int num = 0;
for (int i = 1; i <= 100000000; i++) {
num+=i;
}
}
}