day13_polymorphism

使用接口时,需要注意的以下事项:

  1. ​ 接口没有静态代码块没有构造方法

  2. ​ 一个类只能继承一个父类,但是可以实现多个接口

    一个接口可以继承多个接口,类与类之间是单继承关系,类与接口之间是一种多实现关系

  3. ​ 如果一个类实现了多个接口,出现了重名的抽象方法,只需要重写一次抽象方法

  4. ​ 如果一个类没有重写接口的所有抽象方法,该类必须是抽象类

  5. ​ 如果一个类实现了多个接口,接口当中存在有重名的默认方法,那么实现类一定要对冲突的默认方法进行重写

  6. ​ 如果一个类直接继承了一个父类,又实现了多个接口,父类当中的成员方法和接口中的默认方法存在重名,优先调用父类中的成员方法

    今日内容

  7. ​ 多态

  8. ​ final

  9. ​ 权限修饰符

  10. ​ 内部类

多态

​ 概述:多态是继封装、继承之后面向对象的第三大特性

​ 定义:多态是指同一行为,具有多种不同的表现形式。即同一行为,通过不同的事物,表现出不同的状态。

​ 前提:

  1. ​ 继承或实现【二选一】
  2. ​ 出现父类的引用指向子类对象【格式体现】
  3. ​ 方法的重写【不重写无实际意义】

多态的表现

​ 格式:

父类类型 变量名 = new 子类对象;
变量名.方法名();

备注:父类类型指的是子类对象继承的父类类型,或者是实现的父接口类型

public class Fu{
    public void method(){
        System.out.println("这是父类的method方法!!!");
    }
}
public class Zi extends Fu{ //1.继承
    @Override
    public void method(){
        System.out.println("这是子类的method方法!!!");  //2.重写
    }
}
public class PolymorphismTest{
    public static void main(String [] args){
        //父类引用指向子类对象   //3.父类引用指向子类对象
        Fu fu = new Zi();
        fu.method();//调用的是子类重写后的方法
    }
}

如果在使用多态方式调用方法时,首先检查父类当中是否有该方法,如果没有则编译报错

​ 如果有,执行的是子类重写后的方法

多态的优点

​ 在实际开发中,父类类型作为放啊的形式参数,传递子类对象给方法,进行方法的调用,更能体现出多态的扩展性和便利性。

public abstract class Animal{
    public abstract void eat();
}
public class Dog extends Animal{
    @Override
    public void eat(){
        System.out.println("啃骨头");  //重写
    }
}
public class Cat extends Animal{ 
    @Override
    public void eat(){
        System.out.println("吃鱼");  //重写
    }
}
//测试类
public class PolymorphismTest{
    public static void main(String [] args){
        //根据不同的对象表现不同的eat()内容
        Animal animal1 = new Cat();
        Animal animal2 = new Dog();// 编左运右
        show(animal1);
        show(animal2);
    }
    public static void show(Animal animal){
		animal.eat();
    }
}

说明:用于多态特性的支持,show方法中的形式参数Animal类型,是Dog和Cat的父类型,父类类型接受子类对象,可以把cat对象和dog对象传递给方法

当程序执行过程中,执行eat()方法实际执行的是各自子类对象重写之后的eat方法,不仅仅可以做到替代,在扩展性方面,无论之后出现多少个子类,都可以使用show方法。

(多态下)访问父类中成员变量有两种方式:

  1. ​ 直接通过对象名访问成员变量:看等号左边是谁,优先用谁,如果没有,继续往上找
  2. ​ 间接通过成员方法访问成员变量:看该方法属于谁,优先用谁,如果没有,继续往上找
//定义父类
public class Fu{
	int num = 10;
    public void showNum(){
        System.out.println(num);
    }
}
public class Zi extends Fu{
	int num = 20;
    public void showNum(){
        System.out.println(num);
    }
}
public class PolymorphismTest{
    public static void main(String [] args){
        Fu fu = new Zi();
        System.out.println(fu.num);//10 编左运左
        fu.showNum();// 20 
    }

调用属性:编左运左

调用方法:编左运右

向上转型一定是安全的、正确的,但有一个弊端:无法调用子类特有内容。由此需要向下转型

引用数据类型的转型问题

  • 向上转型:

    ​ 多态本身就是子类类型向父类类型向上转型的过程,这个过程是默认的

    ​ 当一个父类引用指向子类对象,便是向上转型。

父类类型  变量名  = new 子类类型();
  • 向下转型:

    ​ 父类类型向子类类型向下转换的过程,这个过程是强制的。

    ​ 一个已经向上转型的子类对象,将父类引用转为子类引用,可以使用强制转换格式,便是向下转型

子类类型  变量名  = (子类类型) 父类变量名;

转型的异常

​ 在进行向下转换的过程中,一不小心就会出现 java.lang.ClassCastException类型转换异常。

为了避免这种类型转换异常的发生,java提供了 instanceof关键字,给引用变量做类型转换校验

变量名  instanceof  数据类型 
如果变量属于该数据类型,则返回true
如果变量不属于该数据类型,则返回false

所以,我们在类型转换前,最好进行引用变量的类型判断

public class Test{
    public static void main(String []args){
        //向上转型
        Animal animal = new Cat();
        //向下转型
        if(animal instanceof Cat){
            //表明你就是一只猫
            Cat cat = (Cat)animal;
            cat.eat();
            cat.catchMouse();
        }else if(animal instanceof Dog){
            //表明你就是一只狗
            Dog dog = (Dog)animal;
            dog.lookDoor();
        }else{
            //...
        }
    }
}

学习目标:

  • final
  • 权限修饰符
  • 内部类
  • 引用类型

final :最终的、不可改变的

常见的四种用法:

  1. ​ 可以修饰一个类

    public final class 类名称 { }

    特点:当前这个类不能有任何子类,这个类依然拥有父类。

    ​ 如果一个类是final的,那么其中的所有成员方法都无法被重写(无子类)

  2. ​ 可以修饰一个方法

    当方法被final修饰,它是一个最终的方法,不能被覆盖重写。

    修饰符 final 返回值类型 方法名称(参数列表){ }

    注意事项:对于类、方法来说,abstract关键字和final关键字矛盾, 不可同时使用

  3. ​ 可以修饰一个局部变量

    一旦赋值,不可更改

    对于基本数据类型,不变的是变量中的数据值 final int n = 1999;

    对于引用数据类型,不变的是变量中的内存地址值,内容值可以变化 final Person p = new Person();

  4. ​ 可以修饰一个成员变量

    对于成员变量来说,如果使用final关键字修饰,那么这个变量也是不可改变的

    ​ ①由于成员变量具有默认值,使用final后【必须】手动赋值,不再有默认值

    ​ ②由于final的成员变量,要么使用直接赋值(包括使用代码块赋值),要么通过构造方法赋值 【二选一】

    ​ ③必须保证类当中的所有的重载的构造方法,都最终对final成员变量赋值

上一篇:What is the difference between btree and rtree indexing?


下一篇:Polymorphism with C++