黑马程序员_java 抽象类与接口
抽象类:
抽象方法和抽象类必须使用abstract来定义,有抽象方法的类只能被定义成抽象类,
抽象类里可以没有抽象方法。
格式:abstract class A{//如果不写abstract编译出错
public abstract void show();
}//抽象方法必须创建在抽象类中
什么时候用:当多个类中存在相同功能,但功能主体不一样,这时就向上抽取,
只抽取功能定义,不抽取功能主体
特点:1、抽象方法一定定义在抽象类中,不能有方法体
2、抽象方法和类都必须同时用abstract修饰
3、抽象类不能创建对象
|--为什么抽象类不能实例化?
因为抽象类本身不具体,没有具体的实例。
例如:犬科是一个抽象的概念,真正存在的是狼和狗。
4、抽象类中的方法要想被使用,必须有子类复写全部的抽象方法,才能创建子类对象,
否则编译不通过,因为如果子类只复写了部分抽象方法,该子类还是一个抽象类
注意:虽然抽象类不能创建对象,但是抽象类有构造函数!!!并且比其他类还多了abstract,
抽象类中可以没有抽象方法,也可以有非抽象(包括静态)方法,但是抽象方法不能是静态
方法,否则编译失败,因为使用static修饰一个方法时,通过类名就可以直接调用方法,
如果该方法是抽象方法,调用一个没有方法体的方法肯定会引起错误,因此abstract不能
和static同时使用。当使用abstract修饰类时,表明这个类只能被继承,当使用abstract
修饰方法时,表明这个方法必须由子类重写。而final修饰的类不能被继承,final修饰的
方法不能被重写,因此final和abstract不能同时使用。抽象方法必须被子类重写才有意义,
因此abstract和private不能同时修饰方法
|--代码示例:
public class Test {
public static void main(String[] args)
{
Zi z = new Zi("zhangsan", 23);
z.show();//输出:子类中的函数运行了zhangsan..23
z.aa();//输出:bb
}
}
abstract class Fu{
String name;
int age;
Fu(String name, int age)
{
this.name = name;
this.age = age;
}
abstract void show();
static void aa()
{
System.out.println("aa");
}
}
class Zi extends Fu{
Zi(String name, int age)
{
super(name, age);
}
void show()
{
System.out.println("子类中的函数运行了" + name + ".." + age);
}
static void aa()
{
System.out.println("bb");
}
}
模板方法设计模式:当定义功能时,功能的一部分是确定的,但是有一部分是不确定的,
而确定的部分在使用不确定的部分,那么这时就将不确定的部分暴露出去,由子类去完成
|--代码举例:
public class Test {
public static void main(String[] args)
{
SubTime st = new SubTime();
long runTime = st.getTime();
System.out.println("程序的运行时间为:" + runTime);
}
}
abstract class GetTime{
public final long getTime(){
long sTime = System.currentTimeMillis(); //获取开始时间
runTime();
long eTime = System.currentTimeMillis(); //获取结束时间
return eTime - sTime;
}
public abstract void runTime();
}
class SubTime extends GetTime{
public void runTime(){
for(int i = 1; i < 1000; i++){
System.out.println(i);
}
}
}
接口:
概念:
只有抽象方法和常量的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过
接口的形式来表示,但它不是类,是接口(interface)。接口体现的是规范和实现分离的
设计哲学
定义接口:
和类定义不同,定义接口不再使用class关键字,而是使用interface关键字。
语法格式:
修饰符 interface 接口名 {}
接口中成员的特点:
1、成员常量:public static final
2、成员函数:public abstract
接口中的的属性只能是常量,接口里的方法只能是抽象方法,因为接口里定义的是多个类
共同的公共行为规范,因此接口里的所有成员(常量,方法,内部类,枚举类)都用public
修饰,接口中的常量系统会默认增加是static和final两个修饰符,而接口里没有构造器和
初始化块,因此接口里定义的常量只能在定义时指定默认值。接口中的方法只能是抽象
方法,因为系统会自动增加abstract修饰符。接口里定义的内部类、接口、枚举类默认都
是public static修饰
接口不能实例化:
接口不能创建对象,原因和抽象类一样,但可以通过子类实现接口。
子类必须复写接口所有的方法。
接口的特点:
1、接口是对外暴露的规则。
2、接口是程序的功能扩展。
3、接口的出现降低耦合性。
4、接口可以用来多实现。
|--示例:
interface B{}
interface C{}
class A implements B,C{}
5、类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。
|--示例:class B{}
interface C{}
interface D{}
class A extends B implements C,D{}
注意:implements部分必须放在extends部分之后
6、接口与接口之间可以是继承关系,可以多继承
|--示例:
interface B{}
interface C{}
interface A extends B,C{}
实现接口的关键字:implements
|--代码示例:
public class Test {
public static void main(String[] args)
{
S_Stu stu = new S_Stu("张三", 23, "男");
stu.mySelf();
stu.smoking("黄鹤楼");
stu.study("java");
}
}
interface Smoking
{
public abstract void smoking(String sName);
}
abstract class Student
{
int age;
String name;
String sex;
Student(){}
Student(String name,int age,String sex)
{
this.name = name;
this.age = age;
this.sex = sex;
}
abstract void study(String course);
public void sleep()
{
System.out.println("睡觉");
}
}
class S_Stu extends Student implements Smoking
{
S_Stu(){}
S_Stu(String name,int age, String sex)
{
super(name, age, sex);
}
public void smoking(String sName)
{
System.out.println("我抽" + sName);
}
public void study(String course)
{
System.out.println("我学" + course);
}
public void mySelf()
{
System.out.println("我叫:" + name + ",今年" + age + "岁");
}
}
抽象类和接口:
|--相同点:
1、接口和抽象类都不能被实例化,用于被其他类实现和继承
2、接口和抽象类都可以包含抽象方法,实现接口或继承抽象类的子类都必须
实现这些方法。
|--不同点:
1、接口里只能包含抽象方法;抽象类可以包含普通方法
2、接口里不能包含静态方法;抽象类里可以定义静态方法,
只是不能和abstract同时出现
3、接口里只能定义静态常量属性,抽象类里既可以定义普通属性,也可以定义
静态常量属性
4、接口里没有构造器,和初始化块;抽象类里有构造器和初始化块,该构造器
不是用于创建对象,而是让其子类完成抽象类的初始化
5、接口可以多继承,而抽象类只能有一个直接父类