第五天: 面向对象 继承 final 抽象类 接口 多态
1.继承:当多个类(子类 ,也可以叫派生类)有相同的属性和方法时候,我们就把这些共性抽取出来放到另一个类(父类,也可以叫基类)中,这个类叫父类(基类),由这多个类通过extends关键字与另一个类产生子父级关系(就是儿子和父亲关系)。
子类继承父类,通俗理解儿子继承父亲的东西(财产)
java中继承的特点:
1.java中只支持单一继承(一个子类只能继承一个父类,也只能有一个爷爷)
2.支持多层继承
继承关系中成员变量的特点:
1.在继承中,子类只能继承父类非私有成员
2.在子父类关系中,子类与父类成员变量同名时,使用的是子类自己的成员变量
super:父类的引用(不能直接看成是父类对象,它相当于一根
指针指向了父类)
例子:
public class ExtendsTest {
public static void main(String[] args) {
Zi zi = new Zi();
System.out.println(zi.name);
}
}
class Zi extends Fu{
String name="儿子的名字";
public void method(){
String name="局部变量的名字";
System.out.println(name);//局部变量的名字
System.out.println(this.name);//当前对象的引用,当前对象的名字
System.out.println(super.name);//父类的引用,指向父类中名字
}
}
class Fu{
String name="老爸的名字";
}
继承关系中成员方法的特点:
1.在继承中,子类只能继承父类非私有成员方法
2.当父类的方法无法满足子类自身的需求时候,我们就把父类的方法(方法体)重新在写一遍,写成满足子类自身需求的方法(这个就是方法的重写)
3.当子父类成员方法重名时,使用的是子类重写过的方法
(方法重写原因导致----前提(父类的方法无法满足子类自身的需求时))
方法的重载?
在同一个类中,方法名相同,参数列表不同(个数,顺序,类型),与返回值无关
方法的重写? 在子父类关系中,当父类的方法无法满足子类自身的需求时,子类重写了一遍父类的方法 ,其中方法体满足子类自己的需求。
4. 方法重写的前提: 当父类的方法无法满足子类自身的需求时
5.方法重写的标志: @Override
规定子类重写的这个方法与父类的方法声明一模一样,只有方 法体不一样
继承关系中构造方法的特点:
1.父类的构造方法不是被字节直接继承过去,而是子类中构造方法会通过super()去调用父类的构造方法
2.在子父类关系中,为什么调用子类的构造方法时,会先调用父类的构造方法?(扩展)
在继承关系中,因为父类中可能会有成员变量,而子类可以继承并直接使用父类的非私有成员变量,所以父类的非私有成员变量要先依靠无参或者有参构造先进行初始化或者赋值
3.手动调用父类的构造方式要放到有效代码的第一行 ,一次只能调用父类的一个构造方法
4.子类的每一个构造方法都能调用父类的构造方法
继承的优缺点:
优点:
1.提高代码的复用性
2.提高程序的可维护性
缺点:低内聚高耦合
开发原则: 高内聚低耦合
内聚:每一个类自主完成事情的能力
耦合:类与类之间的关联
2. final:最终的,用来修饰变量 方法 类的
修饰的变量变常量 修饰的方法不能被重写 修饰的类不能被继承
常量是可以被继承的
常量取名:每一个单词都要大写,如果有多个单词 用 _链接
final int AGE=20; final MAX_AND_MIN
final修饰的变量一般结合static使用
如果使用static修饰,那么子类的对象 ,子类名,父类名都可以进行调用
3.抽象类
抽象方法:当多个子类中具有相似的方法时,抽取共性(方法声明)到父类中---只有方法声明没有具体方法体的方法是抽象方法。
抽象类:具有抽象方法的类是抽象类,用abstrct关键字修饰
当某个类继承抽象类时,要么自己是一个抽象类,要么自己实现(重写)抽象类中所有的抽象方法。
例子:
public abstract class AbstractTest {
String name;
public void eat() {
System.out.println("吃吃吃");
}
public abstract void run();
}
class A extends AbstractTest{
@Override
public void run() {
System.out.println("正在跑步,,,,,");
}
}
抽象类特点:
1.抽象类不能创建对象(不能实例化)
为什么不能实例化?
1.因为抽象类找那个可能有抽象方法,如果能够实例化,对象就能直接调用抽象方法,而抽象方法没有方法体,调用没有任何意义。
2.抽象类和抽象方法都需要使用abstract关键字修饰
3.抽象方法只能在抽象类中(或者接口中)
4.抽象类中可以存在非抽象方法(方便子类继承)
5.抽象类中一定要有抽象方法吗?不一定
6.单一个类继承抽象类时,要么重写抽象类中所有的抽象方法,要么自身变成一个抽象类。
抽象类中可以存在哪些成员?
1.抽象方法 2.非抽象方法 3.成员变量 4.常量 5.构造方法 存在构造方法的目的是给成员变量进行初始和二次赋值用的。 6.静态方法
abstract不能与哪些关键字共存?
1.不能与private共存
2.不能与final共存
3.不能与statc共存 如果与这些关键字共存,那么抽象方法就没有意义了
4.接口
接口(interface):在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
接口:比抽象类还要抽象的类
为什么会有接口呢?
因为之前继承只能单一继承。所有出现了接口解决这个问题。
接口格式:
interface 接口名{
}
JDK1.8之前接口里面只能存在抽象方法和常量
JDK1.8 default,static修饰的方法可以有具体的方法
JDK1.9 private修饰的方法可以有具体的方法
面试题:抽象类和方法的区别?五颗星
答:
1.JDK8之前抽象类里面可以有抽象方法也可以有非抽象方法,接口里面的方法只能有抽象方法。
2.一个类继承了抽象类的话要么重写抽象类所有的抽象方法,要么他自己就是抽象类,如果一个类实现了接口要重写接口里面所有的方法才可以。
3.一个类只能继承一个抽象类,但是可以实现多个接口。
4.接口中声明的变量默认都是 final 的。抽象类可以包含非 final 的变量。
5.接口中的成员函数默认是 public 的。抽象类的成员函数可以是 private,protected 或者是 public 。
6.接口是比抽象类还要抽象的类,抽象类也不可以被实例化,但是,如果它包含 main 方法的话是可以被调用的。
5.多态
多态:同一种事物有不同的表现形态。例如:水的形态有固态的,液态的,有气态的
水(液态)-------水蒸气(气态)----冰(固态)
老师---小学老师 中学老师 大学老师
动物-- 猫 狗 猪 羊
多态有一个前提:
1存在继承关系(实现接口也可以看成是一种特殊的继承)
2.方法的重写(继承抽象类,和实现接口时)
3.
父类的引用 Animal a
指向 =
子类对象 new Cat()
多态
如果以后我们使用到的某个类是抽象类或者接口,抽象类与接口不能直接实例化
但是我们可以通过多态进行访问父类中的成员
例子:
public class Demo5 {
public static void main(String[] args) {
//父类的引用指向子类对象
//猫是一只动物( a不要就是当成一只猫)
Animal a=new Cat();
//使用成员变量
System.out.println(a.name);
//调用方法
a.eat();
a.method1();
}
}
class Animal{
String name="大狗";
public void eat(){
System.out.println("吃香。。。。");
}
public static void method1(){
System.out.println("这是父类的静态方法。。。");
}
}
class Cat extends Animal{
String name="小花猫";
@Override
public void eat(){
System.out.println("吃鱼。。。");
}
//静态方法
public static void method1(){
System.out.println("这是子类的静态方法。。。。");
}
如果要用子类的成员的话,可以使用强制转换类型(向上转型和向下转型)
public class Demo6 {
public static void main(String[] args) {
//多态:父类的引用指向子类的对象
Anima a=new Dog();//向上转型(小的转大的)
System.out.println(a.name);//这里调用的父类中的name属性
Dog dog=(Dog)a;//向下转型(大的转小的)
System.out.println(dog.name);//这里调用的子类中的name属性
a.eat();//因为动态绑定(重写父类的方法)所以这里是调用子类中的方法
/*总结多态的优缺点
* 缺点: 无法直接访问子类特有的成员
* 优点:
* 1.继承的优点就是多态的优点
* 2.提高程序的可扩展性
* */
//生产小米手机
Factory f=new Factory();
/* f.createXiaoMiNote(new XiaoMiNote());
//生产红米实际
f.createRedMiNote(new RedMiNote());*/
f.createPhone(new XiaoMiNote());
f.createPhone(new RedMiNote());
}
}
//父类
class Anima{
String name="动物";
//因为动态绑定
public void eat(){
System.out.println("吃吃吃。。。。。。。。。");
}
}
//子类
class Dog extends Anima{
String name="小黄";
public void eat(){
System.out.println("吃骨头。。。。。。。。。");
}
}
//手机工厂----生产手机
class Factory{
/* //生产一批小米手机
public void createXiaoMiNote(XiaoMiNote xm){
xm.call();
}
//生产一批红米手机
public void createRedMiNote(RedMiNote rm){
rm.call();
}*/
//多态
public void createPhone(Phone p){
p.call();
}
}
//手机类
class Phone{
//打电话的功能
public void call(){
System.out.println("手机打电话...");
}
}
//小米手机
class XiaoMiNote extends Phone{
//打电话的功能
public void call(){
System.out.println("小米手机打电话...");
}
}
//红米
class RedMiNote extends Phone{
//打电话的功能
public void call(){
System.out.println("红米手机打电话...");
}
}
多态中的成员特点:
1.成员变量
如果只是子类特有时,无法通过父类的引用直接使用
编译时看的是 父类 ,运行的结果看的也是父类
2.成员方法
如果只是子类特有时,无法通过父类的引用直接使用
编译时看的还是父类,运行的结果看的是子类
(动态绑定---方法的重写)
温习继承
Cat c=new Cat()
当字父类成员变量同名时,使用的是子类的成员变量
当子父类成员方法同名时,使用的是子类的成员方法(方法的重写)
3.静态方法
如果只是子类特有时,无法通过父类的引用直接使用
编译时看的还是父类,运行时看的还是父类
Animal a -------a还是Animal
多态最重要的特点:
通过父类的引用无法直接访问子类特有的成员。
一定访问到子类特有的成员?数据类型的转换
总结多态的优缺点
缺点:无法直接访问子类特有的成员
优点:
1.继承的优点就是多态的优点
2.提高程序的可扩展性