猪猪的IT之路---Java成长之路(重写、抽象方法、抽象类、接口、多态)
重写(覆盖,覆写):子类可以重(新编)写继承的父类方法
1.如果父类的所有子类都重写父类的某个方法,那么问?父类的该方法是否有必要存在方法体(方法大括号中的代码),答:该方法体没有存在价值
2.如果父类中某个方法想要继承的子类都重写该方法,那么该方法就不能存在方法体
抽象方法:没有方法体的方法就是抽象方法,抽象方法必须使用abstract关键字修饰
语法:
修饰符 abstract 返回值类型 方法名() ;
提示:抽象方法没有方法体,也就是没有{}
抽象类:存在抽象方法的类必须是抽象类,但是抽象类不一定存在抽象方法,抽象类也是使用了abstract修饰的类
语法:
修饰符 abstract class 类名{
}
抽象类的特点:
1.使用abstract修饰的类
2.类中可以存在抽象方法和普通方法,也可以全是普通方法(后期可以扩展抽象方法)
3.如果抽象类中存在抽象方法,而且该类是某个子类的父类,那么子类必须重写父类抽象方法,否则编译报错
接口:特殊的抽象类,接口中只能存在抽象方法,属性必须是public static修饰的属性(一般很少写)
语法:
public interface 接口名 {
//全是抽象方法
void show();
}
提示:实际开发中每个功能类都应该存在其对应的接口,开发中先有接口后有具体实现(子)类
特点:
1.使用interface来修饰接口,不能有class关键字
2.接口中只能存在抽象方法,而且方法必须是public
abstract修饰的,接口中的方法默认就是public abstract修饰,所有定义抽象方法时可以没有修饰符
3.接口中的属性默认是public
static final的,属性必须是常量
补充:常量:命名必须全大写,定义时必须赋值,而且不能二次更改
4.类和接口的关系是实现关系,也就是说类实现接口,实现等同于继承,只是关键字不同
5.接口允许多实现,接口只能通过子类实现接口,通过关键字implements来实现
子类实现接口语法:
public class 子类名 implements 接口名1,接口名2,……{}
子类继承父类并实现接口语法:
public class 子类名 extends 父类名 implements 接口名1,接口名2,……{}
子类实现多个接口
新增普通父类:
子类继承并实现接口
6.接口和抽象类一样不能创建对象,子类继承抽象类或实现接口都必须重写抽象类和接口中的所有抽象方法后才能创建对象,否则子类也是一个抽象类或接口
Java是单继承语言,但是Java中的接口允许多继承
语法:修饰符 interface 接口名 extends 接口名1,接口名2,….{}
总结:接口和抽象类的区别:
相同点:
1.都包含抽象方法,子类都必须重写所有的抽象方法
2.都不能直接实例化对象(创建对象)
3.都是位于继承的顶端,也就是都是用于被其他类实现或继承
区别:
1.抽象类中可以有抽象方法,也可以有非抽象的普通方法,而接口中只能有抽象方法
2.一个类只能继承一个直接的父类(可能是抽象类)但是可以实现多个接口(接口就弥补了Java的单继承)
3.抽象类是用于描述子类对象应该具备的内容,其子类是一种is…a关系,而接口描述的额外的内容,其实现类是一种like…a关系
接口和抽象类在开发中的选用:
1.优先选用接口,尽量少使用抽象类
2.需要定义子类行为(抽象方法),又需要给子类提供共性功能(普通方法)时才选用抽象类
多态:多种形态,使用多态的前提必须存在继承关系
现实世界中事物存在多种形态,比如学生,学生也是人类的一种,那么具体的一个同学陈尚林既是学生也是人类,就具有两种形态
Java是面向对象的语言,也可以用于描述事物的多种形态,比如Student类继承People类,那么一个Student对象既是Student也是People
Java代码体现多态:
把一个子类的对象(实现类对象)既可以赋值给这个子类变量,也可以赋值给这个子类的父类(接口)变量
比如:Student类继续People类,那么
Student stu = new Student();
People peo = new Student();
总结:
多态的体现:父类的引用变量可以指向子类对象(子类对象可以赋值给父类变量)
多态的前提:必须有父子关系或实现接口关系,否则无法多态
多态的定义语法:
People peo = new
Student();
父类类型 变量名 = new 子类类型();
变量名.方法名()
普通类多态:
public classPeople{}
public class Student extends People{}
People peo = new Student();
抽象类多态:
public abstract class People{}
public class Student extends People{}
People peo = new Student();
接口多态:
public interface People{}
public class Student implement People{}
People peo = new Student();
当父类的某个方法被子类重写,在调用该方法时,调用的是各个子类重写后的方法
在多态使用的情况下成员属性的特点:
在编译和运行时都参考等号左边的所有类来看是否存在该属性,成员变量编译运行看左边
在多态使用的情况下方法的特点:
在编译时参考左边变量的类来看,如果没有该方法,那么编译报错
在运行时参考右边的对象所属类来看,并调用右边的所属类的方法
方法编译看左边,运行看右边
Instanceof关键字:用于判断某个对象是否属于某种数据类型
语法:对象 instanceof 数据类型 //表达式返回boolean值
Student类和Teacher类都继承People类
多态的类型转换:分为向上转型(装箱)和向下转型(拆箱)
向上转换:当有子类对象赋值给一个父类引用变量时就是向上转型,也就是多态本身就是向上转型,这是一种由小变大的过程
父类类型 变量名 = new 子类类型();
如:People p = new
Student();
向下转型:将一个已经向上转换的子类对象通过强制转换把其父类引用变量赋值给子类引用变量,这就是向下转型,如果是直接创建的父类对象是无法向下转换
子类类型 变量名 = (子类类型)父类类型的变量;
如:Student stu =
(Student)p;
多态的好处和坏处:
当将子类对象赋值给父类引用时,会发生向上转型,也就是会将子类对象转为父类类型,向上转型的好处是隐藏子类类型,提高代码的扩展性
但是向上转型有坏处,只能调用父类存在的方法,不能调用子类特有的方法,如果想要调用子类特有方法,那么只能向下转型,只是在向下转型时都应该先判断其是否属于待转类型
总结:
当父类中的方法就能完成所有操作,不需要使用到子类时,应该使用向上转型来提高扩展性
但是当需要使用子类特有方法时,就应该向下转换,转型前必须判断所属类型
实际开发中:
如果存在继承关系,一般都可以使用多态思想进行编程,在创建对象时一般都会讲子类对象赋值给父类变量,同时在定义方法参数时,如果可以使用参数的父类型,那么一般都是直接使用父类类型,方便扩展