1.抽象类概述
抽象类用来描述一种类型应该具备的基本特性与功能,具体如何去完成这些行为由子类通过方法重写来完成.
具有抽象方法的类一定为抽象类.
2.抽象类,方法定义的格式
abstract 在class前修饰类
abstract class 类名{}
3.抽象方法定义的格式
abstract在访问权限后,返回值类型钱修饰方法,方法没有方法体
public abstract 返回值类型 方法名(参数);
/* * 抽象的父类 */ public abstract class Employee{ //抽象方法。需要abstract修饰,并分号;结束 public abstract void work(); } /* * 定义抽象父类的具体子类 */ public class Waiter extends Employee { /* * 重写了父类的抽象方法,加入了方法体,描述出具体逻辑 */ @Override public void work() { System.out.println("为顾客服务"); } } public static void main(String[] args) { //创建一个父类对象不可以,因为该类为抽象类 // Employee e = new Employee(); //创建具体的子类对象 Waiter waiter = new Waiter(); //调用子类重写的父类抽象方法 waiter.work(); }
4.抽象类的特点
抽象类和抽象方法都需要被abstract修饰.抽象方法一定要定义在抽象类中.
抽象类不可以直接创建对象,原因:调用 抽象方法没有意义
只要覆盖了抽象类中所有的抽象方法后,其子类才可以创建对象.否则该子类还是一个抽象类
5.抽象类的构造方法
抽象类的构造方法存在的意义:子类构造方法中通过super语句调用抽象父类的构造方法,为抽象父类中的成员变量赋值,而赋值后的成员变量可以被子类的对象使用
/* * 抽象的父类 */ public abstract class Employee{ //抽象类中定义正常的成员变量 private String name; //构造方法 public Employee() { super(); } //该构造方法,不能直接被程序员调用,因为该类为抽象类,不能直接创建对象. //但是在创建子类对象时,子类的构造方法,可以调用父类的构造方法,为子类对象中的父类对象空间赋值 public Employee(String name) { super(); this.name = name; } public abstract void work(); public String getName() { return name; } public void setName(String name) { this.name = name; } } /* * 定义抽象父类的具体子类 */ public class Waiter extends Employee { public Waiter() { super(); } //子类的构造方法可以调用父类的构造方法 //这里,一个参数的子类构造,调用了父类一个参数的构造,为父类的成员变量赋值 //但是最终还是子类对象自己使用这个成员变量 public Waiter(String name) { super(name); } /* * 重写了父类的抽象方法,加入了方法体,描述出具体逻辑 */ @Override public void work() { System.out.println("为顾客服务"); } } public static void main(String[] args) { //创建具体的子类对象时,子类的构造会调用父类的构造 //为成员变量赋值 Waiter waiter = new Waiter("Rose"); //调用子类重写的父类抽象方法 waiter.work(); System.out.println(waiter.getName()); }
抽象类一定是个父类,因为抽象类时不断抽取共性需求而来的.
抽象类中可以不定义抽象方法,此时仅仅是不让该类创建对象,
6.接口的概念
接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的‘类‘
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成.
//定义格式: public interface 接口名 { 抽象方法1; 抽象方法2; 抽象方法3; }
使用interface代替了原来的class,其他步骤与定义类相同:
接口中的方法均为公共访问的抽象方法
接口中无法定义普通的成员变量
7.接口的使用方式
接口不可以创建对象。
我们使用实现来表示一个类与一个接口之间的关系,这是接口最常用的使用方法。
实现的关键字为implements。
class 类 implements 接口 { 重写接口中方法 }
接口中定义功能,一切类需要具有该功能时均可以实现该接口,只声明了应该具备该方法,是功能的声明。
具体实现类中重写方法,实现功能,是方法的具体实现。
8,接口的注意事项
类单继承类,接口多继承接口,类多实现接口
类可以在继承一个类的同时,实现多个接口
接口与父类的功能可以重复,均代表要具备某种功能,并不冲突
9.接口中成员的特点
接口中可以定义变量,但是变量必须有固定的修饰符修饰,public static final 所有接口中的变量也称之为常量
接口中可以定义方法,方法也有固定的修饰符,public abstract
接口不可以创建对象
子类必须覆盖掉接口中所有的抽象方法后,子类才可以实例化,否则子类是一个抽象类
10.多态的概述
现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。
Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。
最终多态体现为父类引用变量可以指向子类对象。
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。
11.多态类的定义格式
父类类型 变量名 = new 子类类型();
变量名.方法名();
普通类:
父类 变量名 = new 子类();
如: class Fu {}
class Zi extends Fu {}
//类的多态使用
Fu f = new Zi();
抽象类:
抽象类 变量名 = new 抽象类子类();
如:
abstract class Fu { public abstract void method(); }
class Zi extends Fu { public void method(){ System.out.println(“重写父类抽象方法”); } }
//类的多态使用
Fu fu= new Zi();
接口:
接口 变量名 = new 接口实现类();
如:
interface Fu { public abstract void method(); }
class Zi implements Fu { public void method(){ System.out.println(“重写接口抽象方法”); } }
//接口的多态使用
Fu fu = new Zi();
12.多态转型
多态的转型分为向上转型与向下转型两种:
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
父类类型 变量名 = new 子类类型();
如:Person p = new Student();
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,
这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的
子类类型 变量名 = (子类类型) 父类类型的变量;
如:Student stu = (Student) p; //变量p 实际上指向Student对象
13.instanceof
我们可以通过instanceof关键字来判断某个对象是否属于某种数据类型
boolean b = 对象 instanceof 数据类型;