1、abstract关键字
可用来修饰类和成员方法。
类:
用abstract修饰的类表示抽象类,抽象类不能实例化,即不允许创建抽象类本身的实例。
没有用abstract修饰的类称为具体类,具体类可以被实例化。
成员方法:
用abstract修饰的方法表示抽象方法,抽象方法没有方法体。抽象方法用来描述系统具有什么功能,不提供具体的实现。
没有abstract修饰的方法称为具体方法,具体方法具有方法体。
语法规则:
1) 抽象类中可以没有抽象方法,但包含了抽象方法的类必须被定义为抽象类;
2) 没有抽象构造方法,也没有抽象静态方法;也没有final抽象方法
3) 抽象类中可以有非抽象的构造方法;
4) 抽象类及抽象方法不能被final修饰符修饰。
问与答:
Q1:抽象类不允许实例化,思考原因?
答:抽象的东西不能具体化
Q2:既然不允许实例,为什么可以有构造器?
答:子类实例化调用父类构造器
Q3:一个抽象类如果没有抽象方法,可不可以定义为抽象类?如果可以,有什么意义?
答:可以,(抽象类不能被实例化)这样做表示这个类不让其他类实例化该类,只有子类可以
Q4:abstract不能和那些关键字共存?
答:final、static、private
实例:
/**
* 封装和继承都是为多态做准备的 保证了代码的可维护性 多态增强了代码的可拓展性
* 不能使用子类中特有的行为*
*/
public class AbstractDemo {
public static void main(String[] args) {
/**
* 抽象类本身不能实例化
* new Animal是Animal这个抽象类的一个实现类的对象,必须有抽象方法的重写
*/
//匿名内部类,用于只调用一次便不再使用的类
Animai a = new Animal(){
public void sleep(){
System.out.println("输睡");
}
public void eat(){
System.out.println("虎吃头");
}
}.sleep();
}
}
class abstract Animal {
/*
* 当父类只知道子类要有这种行为的时候,但是又不清楚子类对于这种行为的实现细节
* 抽象方法没有方法体
* 有抽象方法的类一定是抽象类,但是抽象类可以有非抽象方法
* 父类有抽象方法,子类要强制实现方法重写
*/
public Animal(){}; //子类可能要被实例化,子类实例化需要走父类构造器,所以父类也有构造器
public abstract void sleep() ;
public abstract void eat() ;
}
class Dog extends Animal {
/**
* 父类中有抽象方法,子类必须强制重写这些抽象方法(非抽象方法不需要)
* 子类如果也是抽象类,那么不需要强制重写父类抽象方法
*/
@Override
public void sleep() {
System.out.println("站着睡");
}
@Override
public void eat() {
System.out.println("狗吃骨头");
}
}
class Cat extends Animal {
@Override
public void sleep() {
System.out.println("趴着睡");
}
@Override
public void eat() {
System.out.println("猫吃鱼");
}
}
2、接口
英文称作interface,在软件工程中,接口泛指供别人调用的方法或者函数。
产 生 原 因:解决多重继承问题。单继承(extends)多实现(implements)
例如Fish类继承Animal类,表明Fish是一种动物,但鱼同样也是一种食物,如何表示这种关系呢? 由于Java语言不支持一个类有多个直接的父类,因此无法用继承关系来描述鱼既是一种食物,又是一种动物,为了解决这一问题,Java语言引入接口类型,简称接口。一个类只能有一个直接的父类,但是可以实现多个接口。 采用这种方式,Java语言对多继承提供了有力的支持。
接口中可以含有变量和方法。这一点有些类似于我们学过的普通的类,不过,具体区别如下:
(1)接口中的变量会被隐式地指定为public static final变量,也只能是public static final变量。并且必须被显式初始化。
public interface A {
int CONST = 1; //合法,CONST默认为public, static, final类型
public static final int OPAQUE = 1; //合法,显示声明为public static final 类型
}
(2)接口中的方法会被隐式地指定为public abstract方法且只能是public abstract方法。
public interface A {
void method1(); //合法,默认为public、abstract类型
public abstract void method2();//合法,显示声明为public、abstract类型
}
(3)换句话说,接口中所有的方法不能有具体的实现,也就是说,接口中的方法必须都是抽象方法。接口是抽象类的另一种形式
(4)接口中没有构造方法,不能被实例化。
(5)接口与接口之间继承关系,且可以多重继承。类与接口之间实现关系,一个类能实现多个接口,类与类之间单继承。
从这里可以隐约看出接口和抽象类的区别,抽象类抽象到极致就是接口,抽象类可存在有方法体的方法,接口中的方法全部为抽象方法。并且一般情况下不在接口中定义变量。
要让一个类遵循某组特地的接口需要使用implements关键字,具体格式如下
class ClassName implements Interface1,Interface2,[....]{
3、抽象类和接口比较:
(1)相同点:
都不能被实例化;
都能包含抽象方法;
(2)不同点:
抽象类中可以为部分方法提供默认的实现,从而避免子类中重复实现它们,提高代码的可重用性,而接口中只能包含抽象方法;一个类只能继承一个直接的父类,这个父类有可能是抽象类;但一个类可以实现多个接口,这是接口的优势所在;
继承:是与不是的关系,
接口:能与不能的关系,接口更多定义的是共有的功能