Java拾贝第四天——面向对象3

Java拾贝不建议作为0基础学习,都是本人想到什么写什么

多态性

面向对象最后一条也是最重要的特性。

多态性主要体现在两方面:

  • 方法的重载与重写
  • 对象的多态性

方法的重写

在Java拾贝第二天方法中提到了方法的重载
现在基于继承Java提供了方法的重写

即子类重写父类的方法:方法名,返回值类型,传参均相同就是重写

public class test3 {
    public static void main(String[] args) {
       Student s =new Student();//实例化子类时会优先实例化父类
       s.say();
    }
}

class Person {
    public Person() {
        System.out.println("父类的无参构造");//实例化任何类都会调用其无参构造方法
    }
    public void say() {
        System.out.println("父类say方法");
    }
}
class Student extends Person {
    @Override
    public void say() {
        System.out.println("子类重写父类say方法");
    }
}
/*
父类的无参构造
子类重写父类say方法
*/

对象的多态性

//实例化对象格式
对象 变量 = new 指向类型;

正常来说实例一个Person对象它指向的应该是Person类

Person p=new Person();

实例一个Student对象它指向的应该是Student类

Student s=new Student();

如果是实例化Person对象指向Student类呢?

public class test3 {
    public static void main(String[] args) {
        Person p=new Student();//Person指向Student
	//它可以调用子类learn方法吗?
    }
}

class Person {
    public Person() {
        System.out.println("父类的无参构造");
    }
    public void say() {
        System.out.println("父类say方法");
    }
}

class Student extends Person {
    public Student() {
        System.out.println("子类的无参构造");
    @Override
    public void say() {
        System.out.println("子类say方法");
    }
    public void learn() {
        System.out.println("子类learn方法");
    }
}

但变量p只能使用父类Person类的方法,也就是说它没有子类的learn方法。

p.learn();//报错

因为Student继承自Person,所以它可以安全的赋值给变量p。这种安全的赋值称之为向上转型

//向上转型
Person p=new Student();

向上转型遵循的规则:

  • 可以调用父类的所有属性和方法(但要遵循访问规则)

  • 不能调用子类独立有的属性和方法(子类有但父类没有)

  • 方法的运行效果具体看指向类型的实现(基于子类重写)

//运行下述代码就可以体现出第三点
public class test3 {
    public static void main(String[] args) {
        Person p = new Student();
        p.say();
    }
}
class Person {
    public void say() {
        System.out.println("父类say方法");
    }
}
class Student extends Person {

    @Override
    public void say() {
        System.out.println("子类say方法");
    }
}
//子类say方法

基于向上转型方法的运行效果具体看指向类型的实现(基于子类重写)

若是子类没有重写父类的say方法,则运行结果是父类的具体实现。

基于子类重写!!!现补充另一条属性看对象。即 属性看对象,方法看指向

public class Test4 {
    public static void main(String[] args) {
        Sub sub = new Sub();
        System.out.println(sub.i);
        Base base = sub;
        System.out.println(base.i);
    }
}
class Base {
    int i = 10;
}

class Sub extends Base {
    int i = 20;
}

在Base类中,整型i默认为10。在Sub类中,整型i默认为20。

根据属性看对象得到上述代码运行结果为20 10。

//根据方法看指向。试想下述代码打印结果
public class Test4 {
    public static void main(String[] args) {
        Sub sub = new Sub();
        System.out.println(sub.i);
        sub.tell();
        Base base = sub;
        System.out.println(base.i);
        base.tell();
    }
}
class Base {
    int i = 10;
    public void tell() {
        System.out.println(this.i);
    }
}
class Sub extends Base {
    int i = 20;
    public void tell() {
        System.out.println(this.i);
    }
}
/*
20
20
10
20
*/

方法看指向

Sub sub = new Sub();//对象Sub指向Sub。
Base base = sub;//对象Base指向Sub。

至此向上转型:

  • 可以调用父类的所有属性和方法(但要遵循访问规则)

  • 不能调用子类特有的属性和方法(子类有但父类没有)

  • 属性看对象,方法看指向

向下转型
向上转型后无法访问子类属性和方法该怎么办呢?为了解决这个问题就需要再向下转型。

和向上转型相反,如果把父类赋值给子类就是向下转型。

public static void main(String[] args) {
        Student s =new Person();//这么转型是错误的!连编译都无法通过

        Person p = new Student();//正确的向下转型
        Student s = (Student) p;
    }
//错误的向下转型
Student s =new Person();

一般来说子类都是父类的拓展,也就是子类属性和方法都比父类要多,这些多的功能不能凭空出现。所以会向下转型失败。

向下转型遵循的规则:

  • 强转前父类指向的是强转后的对象本身

  • 可以调用子类中的所有属性和方法

//第一条什么意思?
	Person p = new Student();
	Student s = (Student) p;//之前父类指向的是Student,现在强转为Student。

//强转后就等于 Student s=new Student();所以当然可以访问子类所有属性和方法

instanceof关键字
instanceof用于判断变量是否是指定类型或者其子类,构成一个布尔表达式

变量 instanceof 类名==布尔表达式
if(变量 instanceof 类名){};

栗子:

Person p = new Person();
System.out.println(p instanceof Person); // true
System.out.println(p instanceof Student); // false 
System.out.println(p instanceof Object); // true 所有类都继承Object

Student s = new Student();
System.out.println(s instanceof Person); // true 子类属于父类
System.out.println(s instanceof Student); // true

Student n = null;
System.out.println(n instanceof Student); // false
System.out.println(n instanceof Object); // false

如果一个变量指向null,使用instanceof判断永远为false。

posted @ 2023-10-17 22:02  rowbed  阅读(6)  评论(0编辑  收藏  举报