目录
我们之前所说的猫,狗,熊猫,狮子等等都是动物具体的例子,而动物本身是一个抽象的概念。实际上,抽象的东西不能本身不应该被实例化。并且动物中吃的方法应该也不是一个具体的实现,以及所有动物共同拥有的方法在动物中应该都是抽象的表现。
现在,我们把一个不具体的功能,叫做抽象方法,而一个类中如果有抽象方法,这个类就称作抽象类
1.抽象类的特点
1)抽象类和抽象方法都要用一个关键字修饰——abstract关键字
修饰一个类:放在class的前面
举例:abstract class Aniaml3{}
修饰一个方法:放在权限修饰符后面(注意:抽象方法没有方法体,直接以;结尾)
举例:public abstract void show();
abstract class Animal3{
// public abstract void eat(){}; 报错。java: 抽象方法不能有主体
public abstract void eat();
public abstract void drink();
}
2)有抽象方法的类一定是抽象类,具体的类中不能写抽象方法
//错误,有抽象方法的类一定要是抽象类
//class Demo2 {
// public abstract void fun1();
//}
3)抽象类不一定要有抽象方法
abstract class Demo2{
}
4)抽象类不能被实例化
abstract class Demo2{
}
public class AbstractDemo1 {
public static void main(String[] args) {
// Demo2 demo2 = new Demo2(); //报错。java: com.tutu.wjq.day11.Demo2是抽象的; 无法实例化
}
}
既然不能被实例化,那么写在抽象类中的方法如何被调用呢?抽象类如何创建?
通过多态的形式,使用具体的子类去实例化调用方法,专业术语称之为:抽象多态
5)如果继承抽象类的是一个具体的子类,需要重写该抽象类中所有的抽象方法
abstract class Animal3{
public abstract void eat();
public abstract void drink();
}
//如果继承抽象类的是一个具体的子类,需要重写该抽象类中所有的抽象方法
class Dog3 extends Animal3{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void drink() {
System.out.println("狗喝水");
}
}
public class AbstractDemo1 {
public static void main(String[] args) {
//利用具体子类多态形式创建对象
Animal3 a = new Dog3();
a.eat();
a.drink();
}
}
6)如果继承抽象类的也是一个抽象类,可以不去重写父类中的抽象方法,也可以选择性的去重写
abstract class Demo2{
public abstract void fun();
public abstract void fun2();
}
//如果继承抽象类的也是一个抽象类,可以不去重写父类中的抽象方法,也可以选择性的去重写
abstract class Demo3 extends Demo2{
@Override
public void fun() {
System.out.println("抽象类Demo3中重写了fun方法");
}
}
2.抽象类的成员特点
1)成员变量
既可以是变量,也可以是常量
abstract class Animal4 {
int a = 20;
final int b = 100;
}
class Cat4 extends Animal4 {
}
public class AbstractDemo2 {
public static void main(String[] args) {
Animal4 a = new Cat4();
System.out.println(a.a); //20
System.out.println(a.b); //100
}
}
2)构造方法
可以存在构造方法
但是我们知道抽象类不能被实例化,这里的构造方法意义是什么呢?
要想初始化子类,必须先初始化父类,这里的构造方法就是初始化父类的作用
abstract class Animal4 {
int a = 20;
final int b = 100;
Animal4() {
System.out.println("这是Animal4类中的无参构造方法");
}
}
class Cat4 extends Animal4 {
}
public class AbstractDemo2 {
public static void main(String[] args) {
Animal4 a = new Cat4();
System.out.println(a.a); //20
System.out.println(a.b); //100
}
}
3)成员方法
可以是抽象方法,但是具体的子类必须要重写该方法
也可以不是抽象方法,提高代码的复用性(父类有的方法,子类应该也有,继承过来的,不想每个子类都写一遍,直接在父类定义好就可以了)
abstract class Animal4 {
int a = 20;
final int b = 100;
public abstract void eat();
public void show() {
System.out.println("这是父类中不是抽象方法的show");
}
}
class Cat4 extends Animal4 {
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
public class AbstractDemo2 {
public static void main(String[] args) {
Animal4 a = new Cat4();
System.out.println(a.a); //20
System.out.println(a.b); //100
a.eat();
a.show();
}
}
2.抽象类练习
1)抽象类改进猫狗案例
补充知识:生成重写的快捷键:alt+enter
abstract class Animal5{
//定义一个吃饭的抽象方法,不给出具体的实现
public abstract void eat();
//定义一个睡觉的抽象方法,不给出具体的实现
public abstract void sleep();
}
//快捷键 生成重写方法 alt+enter
class Dog5 extends Animal5{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("狗侧着睡");
}
}
class Cat5 extends Animal5{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫趴着睡");
}
}
public class AbstractTest1 {
public static void main(String[] args) {
//抽象多态创建一个对象
Animal5 a = new Dog5();
a.eat();
a.sleep();
//抽象多态创建第二个对象
Animal5 b = new Cat5();
b.eat();
b.sleep();
}
}
2)
假设我们在开发一个系统时需要对员工类进行设计,员工包含三个属性:姓名,工号,以及工资 经理也是员工,除了含有员工的属性外,还有奖金属性 请使用继承的思想设计出员工类和经理类,要求类中提供必要的方法进行属性访问 分析: 普通员工: 成员变量:姓名,工号,工资 成员方法:工作(敲代码) 经理: 成员变量:姓名,工号,工资,奖金 成员方法:工作(做PPT)
abstract class Staff {
private String name;
private String id;
private int salary;
public Staff() {
}
public Staff(String name, String id, int salary) {
this.name = name;
this.id = id;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
public abstract void work();
}
class CommonStaff extends Staff {
public CommonStaff() {
}
public CommonStaff(String name, String id, int salary) {
super(name, id, salary);
}
@Override
public void work() {
System.out.println("敲代码");
}
}
class Manger extends Staff {
private int bonus;
public Manger(int bonus) {
this.bonus = bonus;
}
public Manger(String name, String id, int salary, int bonus) {
super(name, id, salary);
this.bonus = bonus;
}
@Override
public void work() {
System.out.println("做PPT");
}
}
public class AbstractTest4 {
public static void main(String[] args) {
//创建第一个对象
Staff s1 = new CommonStaff("小王", "WS0001", 10000);
s1.work();
//创建第二个对象
Staff s2 = new Manger("小宋", "SS0001", 20000, 200000);
s2.work();
}
}
3.抽象类的小问题
1)一个类如果没有抽象方法,可不可以定义成抽象类?
可以,意义是什么呢?
橙汁,水,牛奶这些东西都拥有共同的特点,都是液体。我们把这些相同的行为概念归结成一个类,假设叫做液体。至于后面有没有抽象方法,取决于这些东西有没有相同的功能
只要说有着相同的本质,但是没有实际相同的行为,我们就可以只定义一个抽象类
2)抽象类中可以存在哪些关键字?
abstract可以和public关键字共存
abstract class YeTi {
//abstract可以和public关键字共存
public abstract void show();
}
abstract和private关键字冲突
私有的只能在本类中访问,而又想让别人重写,就需要别人拿到你,但是你是私有的,冲突
abstract class YeTi {
//abstract和private关键字冲突
//报错。java: 非法的修饰符组合: abstract和private
// private abstract void show2();
}
abstract和static关键字冲突
本来是抽象的类,要么写具体的方法,要么不写,但是抽象方法是静态的,可以直接调用,违背理论
abstract class YeTi {
//abstract和static关键字冲突
//报错。java: 非法的修饰符组合: abstract和static
// static abstract void show3();
}
abstract和final关键字冲突
被final修饰的方法不能被重写,可以继承可以使用,但是抽象的目的就是让子类重写,冲突
abstract class YeTi {
//abstract和final关键字冲突
//报错。java: 非法的修饰符组合: abstract和final
// final abstract void show4();
}