抽象类
定义一个类时,常常需要定义一些成员方法用于描述类的行为特征,但有时这些方法的实现方式是无法确定的。例如,前面定义的 Animal 类中的 shout ()方法用于描述动物的叫声,但是不同的动物叫声也不相同,因此在 shout ()方法中无法准确描述动物的叫声。
针对上面描述的情况, Java 提供了抽象方法来满足这种需求。抽象方法是使用 abstract 关键字修饰的成员方法,抽象方法在定义时不需要实现方法体。抽象方法的语法格式如下:
abstract 返回值类型方法名称(参数列表);
当一个类包含了抽象方法,该类就是抽象类。抽象类和抽象方法一样,必须使用abstract关键字进行修饰
abstract class 抽象类名称{
属性;
访问权限 返回值类型 方法名称(参数){ //普通方法
return 返回值;
}
访问权限 abstract 返回值类型 抽象方法名称(参数); //抽象方法,无方法体
}
抽象类定义的规则;
1.包含抽象方法的类必须是抽象类
2.声明抽象类和抽象方法时都要使用abstract关键字修饰
3.抽象方法只需要声明而不需要实现
4.如果一个非抽象类继承了抽象类之后,那么该类必须重写抽象类中的全部抽象方法
abstract class Animal{
//定义抽象方法
abstract void shout();
}
class Dog extends Animal{
void shout(){
System.out.println("汪汪~~");
}
}
注意:使用abstract关键字修饰的抽象方法不能使用private关键字修饰,因为抽象方法必须被子类实现,如果使用了private关键字修饰抽象方法,则子类无法实现该方法。
接口
在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了static和final变量。
- 接口不是被类继承了,而是要被类实现。
- 接口支持多重继承。
[public] interface 接口名 [extends 接口1,接口2,...]{
[public] [ststic] [final] 数据类型 常量名=常量;
[public] [abstract] 返回值的数据类型 方法名(参数列表);
[public] static 返回值的数据类型 方法名(参数列表){}
[public] default 返回值的数据类型 方法名(参数列表){}
}
//定义接口实现类的语法
修饰符 class 类名 implements 接口1,接口...{
...
}
接口的实现类必须实现接口中的所有抽象方法
修饰符 class 类名 extends 父类名 implements 接口1,接口2,...{
....
}
//定义接口Animal
interface Animal{
public String name="牧羊犬";
public void shout();
public void info();
}
//定义抽象类
abstract class Action{
public abstract void eat();
}
//定义Dog类继承Action抽象类,并实现Animal接口。
class Dog extends Action implements Animal{
//重写Action,Animal中的eat shout info抽象方法
public void eat(){
System.out.println("喜欢吃骨头");
}
@Override
public void shout() {
System.out.println("汪汪~~");
}
@Override
public void info() {
System.out.println("名称:"+name);
}
}
class Main{
public static void main(String[] args){
Dog dog=new Dog();
dog.eat();
dog.info();
dog.shout();
}
}
在Java中,接口不允许继承抽象类,但允许接口继承接口,并且一个接口允许同时继承多个接口。
重写接口中声明的方法时,需要注意以下规则:
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
在实现接口的时候,也要注意一些规则:
- 一个类可以同时实现多个接口。
- 一个类只能继承一个类,但是能实现多个接口。
- 一个接口能继承另一个接口,这和类之间的继承比较相似。
多态
interface Animal{
public void shout();
}
class Dog implements Animal{
@Override
public void shout() {
System.out.println("汪汪~~");
}
}
class Cat implements Animal{
@Override
public void shout() {
System.out.println("喵喵~~");
}
}
class Main{
public static void main(String[] args){
Animal dog=new Dog();//向上转型为Animal
Animal cat=new Cat();//向上转型为Animal
dog.shout();;
cat.shout();
}
}
对象类型转换
1.向上转型:子类对象->父类对象
2.向下转型:父类对象->子类对象
class Animal{
public void shout(){
System.out.println("喵喵");
}
}
class Dog extends Animal{
@Override
public void shout() {
System.out.println("汪汪~~");
}
public void eat(){
System.out.println("爱吃骨头");
}
}
class Main{
public static void main(String[] args){
Dog dog=new Dog();
Animal an=dog;//向上转型
an.shout();
}
}
如果对象发生了向上转型后,调用的方法一定是被子类重写过的方法
父类Animal的对象an是无法调用Dog类中的eat()方法的,因为eat()方法只在子类中定义,而没有在父类中定义。
向下转型:一般是为了重新获得因为向上转型而丢失的子类特性。对象在进行向下转型前,必须先进行向上转型,否则将出现对象转换异常。
父类类型 父类对象=子类实例;
子类类型 子类对象=(子类)父类对象;
class Animal{}
class Dog extends Animal{}
class Main{
psvm{
Animal an=new Dog();
Dog dog=(Dog)an;
}
}
向下转型时,不能直接将父类实例强制转换为子类实例,否则程序会报错。eg:Dog dog=(Dog)new Animal();
instanceof关键字
instanceof:判断一个对象是否是某个类的实例,语法如下:
对象 instanceof 类(或接口)
如果“对象”是指定的类或接口的实例对象,则返回true,否则返回false。