200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Java---面向对象编程三大特征【封装 继承 多态】及super关键字 方法重写/覆盖(不

Java---面向对象编程三大特征【封装 继承 多态】及super关键字 方法重写/覆盖(不

时间:2019-06-21 17:38:35

相关推荐

Java---面向对象编程三大特征【封装 继承 多态】及super关键字 方法重写/覆盖(不

文章目录

三大特征面向对象编程-封装封装介绍封装的理解和好处封装的实现步骤(三步)封装的简单案例封装与构造器封装的练习 面向对象编程-继承为什么需要继承继承基本介绍和示意图继承的基本语法入门案例(修改上述代码)继承带来的便利继承的深入讨论/细节问题1.子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,可以间接访问,但要通过公共的方法去访问2.子类必须调用父类的构造器,完成父类的初始化3.当创建子类对象是,不管使用子类的哪一个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。4.如果希望子类指定去调用父类的某个构造器,则在子类构造器中显式的调用一下:5.super在使用时,需要放在构造器第一行(super只能在构造器中使用)6.super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器7.java所有类都是Object类的子类8.父类构造器的调用不限于直接父类 将一直往上追溯直到Object类(顶级父类)9.子类最多只能继承一个父类(指直接继承),即java中是单继承机制10.不能滥用继承,子类和父类之间必须满足is-a(是一个XXX)的逻辑关系 继承的本质分析(重要)子类创建的内存布局按照查找关系来返回信息 super关键字基本介绍基本语法super细节1.调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。 super和this的比较 方法重写/覆盖(override)基本介绍注意事项和使用细节方法重装和方法重写比较 面向对象编程-多态(非常重要)多【多种】态【状态】基本介绍多态的具体体现1.方法的多态(重写和重载就体现出多态)2.对象的多态(核心,困难,重点)3.多态的使用案例4.多态注意事项和细节讨论多态的前提是:两个对象(类)存在继承关系多态的向上转型多态的向下转型 5.属性没有重写的说法,属性的值看编译类型6.instanceOf比较操作符 多态的应用多态数组多态数组(案例升级) 多态参数

三大特征

面向对象编程有三大特征:封装,继承和多态。

面向对象编程-封装

封装介绍

封装(encapsulation)就是把抽象出的数据【属性】和堆数据的操作【方法】封装在一起,数据被保护在内部,程序的其他部分只有通过被授权的操作【方法】,才能对数据进行操作。

封装的理解和好处

1.隐藏实现细节

2.可以对数据进行验证,保证安全合理

封装的实现步骤(三步)

1.将属性进行私有化private【不能直接修改属性】

2.提供一个公共的(public)set方法,用于对属性判断并赋值

public void setXxx(类型 参数名){//Xxx表示某个属性//加入数据验证的业务逻辑属性 = 参数名;}

3.提供一个公共的get方法,用于获取属性的值

public XX getXxx(){//权限判断,Xxx表示某个属性return xx;}

封装的简单案例

写一个程序,不能随便查看人的年龄,工资等隐私,并对设置的年龄进行合理的验证。年龄合理就设置,否则给默认。年龄必须在1-120,年龄,工资不能直接查看,name的长度在2-6个字之间

import java.util.Scanner;public class Encap {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Person person = new Person();person.setName("jackfafasfasf");person.setAge(20);person.setSalary(1000);// System.out.println(person.info());System.out.println(person.getSalary());System.out.println(person.getName());}}class Person {public String name;//名字公开private int age; //年龄私有化private double salary; //薪水私有化//自己写set和get太慢了,可以使用快捷键(Alt + Insert),然后根据要求完善代码public String getName() {return name;}public void setName(String name) {if (name.length() >= 2 && name.length() <= 6) {this.name = name;}else{System.out.println("名字长度不在范围内,按默认处理");this.name = "未知者";}}public int getAge() {return age;}public void setAge(int age) {if (age >= 1 && age <= 120) {this.age = age;} else {System.out.println("年龄需要在1-120岁之间,你输入的不符,默认年龄为18");this.age = 18;//给一个默认年龄}}public Double getSalary() {System.out.print("请输入密码:");Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();if (num == 123456) {return salary;} else {System.out.println("密码错误");return null;}}public void setSalary(double salary) {this.salary = salary;}//写一个方法,返回属性信息public String info() {return "信息为 name=" + name + " age=" + age + "salary=" + salary;}}

封装与构造器

import java.util.Scanner;public class Encap {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);Person person = new Person();person.setName("jackfafasfasf");person.setAge(20);person.setSalary(1000);// System.out.println(person.info());System.out.println(person.getSalary());System.out.println(person.getName());Person person1 = new Person("小白",18,1000);System.out.println(person1.info());}}class Person {public String name;//名字公开private int age; //年龄私有化private double salary; //薪水私有化public Person() {}public Person(String name, int age, double salary) {// this.name = name;// this.age = age;// this.salary = salary;setAge(age);//等价于this.setAge(age);setSalary(salary);setName(name);}//自己写set和get太慢了,可以使用快捷键(Alt + Insert),然后根据要求完善代码public String getName() {return name;}public void setName(String name) {if (name.length() >= 2 && name.length() <= 6) {this.name = name;}else{System.out.println("名字长度不在范围内,按默认处理");this.name = "未知者";}}public int getAge() {return age;}public void setAge(int age) {if (age >= 1 && age <= 120) {this.age = age;} else {System.out.println("年龄需要在1-120岁之间,你输入的不符,默认年龄为18");this.age = 18;//给一个默认年龄}}public Double getSalary() {System.out.print("请输入密码:");Scanner scanner = new Scanner(System.in);int num = scanner.nextInt();if (num == 123456) {return salary;} else {System.out.println("密码错误");return null;}}public void setSalary(double salary) {this.salary = salary;}//写一个方法,返回属性信息public String info() {return "信息为 name=" + name + " age=" + age + "salary=" + salary;}}

封装的练习

创建程序,在其中定义两个类:Account和AccountTest类体会Java的封装性。

1.Account类要求具有属性:姓名(长度为2位3位或4位)、余额(必须>20)、密码(必须是6位),如果不满足,则给出提示信息,并给默认值。

2.通过setXxx的方法给Account的属性赋值。

3.在AccountText中测试

package com.fspdu.encap;public class Account {private String name;private double banlance;private String pwd;public Account() {}public Account(String name, double banlance, String pwd) {this.setName(name);this.setBanlance(banlance);this.setPwd(pwd);}public String getName() {return name;}public String setName(String name) {if(name.length() >= 2 && name.length() <= 6) {this.name = name;return name;}else{System.out.println("名字不规范,按默认处理");this.name = "无名者";return name;}}public double getBanlance() {return banlance;}public void setBanlance(double banlance) {if(banlance > 20) {this.banlance = banlance;}else{System.out.println("余额必须大于20,在此按默认0处理");}}public String getPwd() {return pwd;}public void setPwd(String pwd) {if(pwd.length() == 6) {this.pwd = pwd;}else{System.out.println("密码必须是6位");}}public void info(){System.out.println("name:" + name + "banlance:" + banlance + "pwd:" + pwd);}}

package com.fspdu.encap;public class AccounText {public static void main(String[] args) {Account account = new Account("小",1,"12345");account.info();}}

面向对象编程-继承

为什么需要继承

看一个问题,我们编写了两个类,一个是Pupil类(小学生),一个是Graduate(大学毕业生)。

//小学生->模拟小学生考试情况public class Pupic {public String name;public int age;private double score;public void setScore(double score) {this.score = score;}public void testing(){System.out.println("小学生" + name + "正在考小学数学");}public void showInfo(){System.out.println("学生名字:" + name + "年龄:" + age + "分数:" + score);}}

//模拟大学生考试情况public class Graduate {public String name;public int age;private double score;public void setScore(double score) {this.score = score;}public void testing(){System.out.println("大学生" + name + "正在考高等数学");}public void showInfo(){System.out.println("学生名字:" + name + "年龄:" + age + "分数:" + score);}}

public class Extends01 {public static void main(String[] args) {Pupic pupic = new Pupic();pupic.name = "小白";pupic.age = 15;pupic.testing();pupic.setScore(100);pupic.showInfo();System.out.println("======================");Graduate graduate = new Graduate();graduate.name = "大白";graduate.age = 18;graduate.testing();graduate.setScore(150);graduate.showInfo();}}

测试结果:

小学生小白正在考小学数学

学生名字:小白 年龄:15 分数:100.0

======================

大学生大白正在考高等数学

学生名字:大白 年龄:18 分数:150.0

我们发现两个类的属性和方法有很多是相同的,怎么办?这就用到了继承(代码复用性)。

继承基本介绍和示意图

继承可以解决代码复用,让我们的编程更加靠近人类思维。当多个类存在相同的属性(变量)和方法时,可以从这些类中抽象出父类,在父类中定义这些相同的属性和方法,所有的子类不需要重新定义这些属性和方法,只需要通过extends来声明继续父类即可。

继承的基本语法

class 子类 extends 父类{

}

1.子类就会自动拥有父类定义的属性和方法

2.父类又叫超类,基类

3.子类又叫派生类

入门案例(修改上述代码)

父类

package com.fspdu.extend.improve;//父类,是Pupil和Graduate的父类public class Student {//共有属性public String name;public int age;private double score;//共有方法public void setScore(double score) {this.score = score;}public void showInfo(){System.out.println("学生名字:" + name + " " + "年龄:" + age + " " + "分数:" + score);}}

两个子类

package com.fspdu.extend.improve;public class Pupil extends Student{public void testing(){System.out.println("小学生" + name + "正在考小学数学");}}

package com.fspdu.extend.improve;public class Graduate extends Student{public void testing(){System.out.println("大学生" + name + "正在考高等数学");}}

测试

package com.fspdu.extend.improve;public class Extends01 {public static void main(String[] args) {Pupil pupil = new Pupil();pupil.name = "小白";pupil.age = 10;pupil.testing();pupil.setScore(100);pupil.showInfo();Graduate graduate = new Graduate();graduate.name = "小黑";graduate.age = 18;graduate.testing();graduate.setScore(150);graduate.showInfo();}}

测试结果:

小学生小白正在考小学数学

学生名字:小白 年龄:10 分数:100.0

大学生小黑正在考高等数学

学生名字:小黑 年龄:18 分数:150.0

继承带来的便利

1.代码复用性提高

2.代码的扩展性和维护性提高

继承的深入讨论/细节问题

1.子类继承了所有的属性和方法,但是私有属性和方法不能在子类直接访问,可以间接访问,但要通过公共的方法去访问

父类

package com.fspdu.extend;public class Base {//父类public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public int getN4(){return n4;}public Base(){System.out.println("父类无参构造器运行");}public void test100(){System.out.println("test100");}protected void test200(){System.out.println("test200");}void test300(){System.out.println("test300");}private void test400(){System.out.println("test400");}public void test4(){test400();}}

子类

package com.fspdu.extend;public class Sub extends Base{//子类public Sub(){System.out.println("子类无参构造器运行");}public void sayOK(){System.out.println(n1 + " " + n2 + " " + n3 + " " + getN4());test100();test200();test300();test4();}}

测试

package com.fspdu.extend;public class ExtendsDetail {public static void main(String[] args) {Sub sub = new Sub();sub.sayOK();}}

测试结果:

父类无参构造器运行

子类无参构造器运行

100 200 300 400

test100

test200

test300

test400

2.子类必须调用父类的构造器,完成父类的初始化

观察上述测试结果:父类无参构造器在子类无参构造器被调用之前先被调用,原因是Sub类里面隐藏了一句话(编译器默认),默认调用父类的无参构造器。

public Sub(){super();//默认调用父类的无参构造器System.out.println("子类无参构造器运行");}

3.当创建子类对象是,不管使用子类的哪一个构造器,默认情况下总会去调用父类的无参构造器,如果父类没有提供无参构造器,则必须在子类的构造器中super去指定使用父类的哪个构造器完成对父类的初始化工作,否则,编译不会通过。

父类

package com.fspdu.extend;public class Base {//父类public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public int getN4(){return n4;}public Base() {System.out.println("父类无参构造器运行");}public void test100() {System.out.println("test100");}protected void test200(){System.out.println("test200");}void test300(){System.out.println("test300");}private void test400(){System.out.println("test400");}public void test4(){test400();}}

子类

package com.fspdu.extend;public class Sub extends Base{//子类public Sub(){super();//默认调用父类的无参构造器System.out.println("子类无参构造器运行");}public Sub(String cchar){System.out.println("子类有参构造器运行");}public void sayOK(){System.out.println(n1 + " " + n2 + " " + n3 + " " + getN4());test100();test200();test300();test4();}public void exce(){System.out.println("===========");}}

测试

package com.fspdu.extend;public class ExtendsDetail {public static void main(String[] args) {Sub sub = new Sub();sub.sayOK();Sub sub1 = new Sub("aaa");sub1.exce();}}

测试结果:

父类无参构造器运行

子类无参构造器运行

100 200 300 400

test100

test200

test300

test400

父类无参构造器运行

子类有参构造器运行

===========

父类

package com.fspdu.extend;public class Base {//父类public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public int getN4(){return n4;}// public Base() {// System.out.println("父类无参构造器运行");// }public Base(String name){System.out.println("父类有参构造器运行");}public void test100() {System.out.println("test100");}protected void test200(){System.out.println("test200");}void test300(){System.out.println("test300");}private void test400(){System.out.println("test400");}public void test4(){test400();}}

子类

package com.fspdu.extend;public class Sub extends Base{//子类public Sub(){super("fsp");//(父类没有无参构造器,用super指定父类构造器完成对父类的初始化)System.out.println("子类无参构造器运行");}public Sub(String cchar){super("fsp");System.out.println("子类有参构造器运行");}public void sayOK(){System.out.println(n1 + " " + n2 + " " + n3 + " " + getN4());test100();test200();test300();test4();}public void exce(){System.out.println("===========");}}

测试

package com.fspdu.extend;public class ExtendsDetail {public static void main(String[] args) {Sub sub = new Sub();sub.sayOK();Sub sub1 = new Sub("aaa");sub1.exce();}}

测试结果:

父类有参构造器运行

子类无参构造器运行

100 200 300 400

test100

test200

test300

test400

父类有参构造器运行

子类有参构造器运行

===========

4.如果希望子类指定去调用父类的某个构造器,则在子类构造器中显式的调用一下:

public Xxx(....,....) {super(....);System.out.println(".....");}

5.super在使用时,需要放在构造器第一行(super只能在构造器中使用)

6.super()和this()都只能放在构造器第一行,因此这两个方法不能共存在一个构造器

7.java所有类都是Object类的子类

8.父类构造器的调用不限于直接父类 将一直往上追溯直到Object类(顶级父类)

9.子类最多只能继承一个父类(指直接继承),即java中是单继承机制

思考:如何让A类继承B类和C类?【A继承B,然后B继承C】

10.不能滥用继承,子类和父类之间必须满足is-a(是一个XXX)的逻辑关系

Music extends Person //不合理

Cat extends Animal //合理

继承的本质分析(重要)

子类创建的内存布局

按照查找关系来返回信息

super关键字

基本介绍

super代表父类的引用,用于访问父类的属性、方法、构造器

基本语法

1.访问父类的属性,但不能访问父类的private属性:super.属性名;

2.访问父类的方法,不能访问父类的private方法:super.方法名(参数列表);

3.访问父类的构造器:super(参数列表);只能放在构造器的第一句,只能出现一句

父类

package com.fspdu.super_;public class A {public int n1 = 100;protected int n2 = 200;int n3 = 300;private int n4 = 400;public void test100(){}protected void test200(){}void test300(){}private void test400(){}}

子类

package com.fspdu.super_;public class B extends A{public void hi(){System.out.println(super.n1 + " " + super.n2 + " " + super.n3);}public void ok(){super.test100();super.test200();super.test300();}public B(){super();}}

super细节

1.调用父类的构造器的好处(分工明确,父类属性由父类初始化,子类的属性由子类初始化)

2.当子类中有和父类中的成员(属性和方法)重名时,为了访问父类的成员,必须通过super。如果没有重名,使用super、this、直接访问是一样的效果

this等价于直接访问:先找本类,如果有,则调用;如果没有,则找父类(父类有就调用);如果父类没有,则找父类的父类,直到Object类(提示:如果查找方法或者属性的过程中,找到了但是不能访问,则报错;如果查找过程中没有找到,则提示方法不存在)

super:跳过本类(子类)直接查找父类,后续规则一样

3.super的访问不限于直接父类,如果爷爷类和本类中有同名的成员,也可以使用super去访问爷爷类的成员;如果多个基类中都有同名的成员,使用super访问遵循就近原则。

super和this的比较

方法重写/覆盖(override)

基本介绍

简单的说:方法覆盖(重写)就是子类有一个方法,和父类的某个方法的名字、返回类型、参数一样,那么我们就说子类的这个方法覆盖(重写)了父类的那个方法

注意事项和使用细节

方法重写也叫方法覆盖,需要满足下面的条件

1.子类的方法的参数,方法名称,要和父类方法的参数,方法名称完全一样

2.子类方法的返回类型和父类方法返回类型一样,或者是父类返回类型的子类

(比如父类返回类型是Object,子类方法返回类型是String)

父类---public Object getInfo(){}

子类---public String getInfo(){}

3,子类方法不能缩小父类方法的访问权限,允许扩大**

public > protected > 默认 > private

父类---void sayOk(){}

子类---public void sayOk(){}

方法重装和方法重写比较

面向对象编程-多态(非常重要)

提高代码的复用性,有利于代码维护

多【多种】态【状态】基本介绍

方法或对象具有多种形态。是面向对象的第三大特征,多态是建立在封装和继承基础之上的

多态的具体体现

1.方法的多态(重写和重载就体现出多态)

package com.fspdu.poly_;public class PolyMethod {public static void main(String[] args) {//方法重载体现多态A a = new A();//我们通过不同的参数个数去调用sum方法,就会去调用不同的方法//因此对sum方法来说,就是多种状态的体现System.out.println(a.sum(11,22));System.out.println(a.sum(11,22,33));//方法重写体现多态B b = new B();a.say();b.say();}}class B{public void say(){System.out.println("B say()方法被调用");}}class A extends B{public int sum(int n1,int n2){return n1 + n2;}public int sum(int n1,int n2,int n3){return n1 + n2 + n3;}public void say(){System.out.println("A say()方法被调用");}}

33

66

A say()方法被调用

B say()方法被调用

2.对象的多态(核心,困难,重点)

重要的几句话:

(1)一个对象的编译类型和运行类型可以不一致

(2)编译类型在定义对象时,就确定了,不能改变

(3)运行类型是可以变化的

(4)编译类型看定义时 = 号的左边,运行类型看 = 号的右边

例:

Animal animal = new Dog();【animal编译类型是Animal,运行类型Dog】

animal = new Cat();【animal的运行类型变成了Cat,编译类型仍然是Animal】

父类

package com.fspdu.poly_.objpoly_;public class Animal {public void cry(){System.out.println("动物在叫");}}

子类

package com.fspdu.poly_.objpoly_;public class Dog extends Animal{public void cry() {System.out.println("dog.cry---小狗汪汪");}}

package com.fspdu.poly_.objpoly_;public class Cat extends Animal{public void cry(){System.out.println("cat.cry---小猫喵喵");}}

测试

package com.fspdu.poly_.objpoly_;public class PolyObject {public static void main(String[] args) {//对象多态的特点//animal 编译类型是Animal//运行类型 Dog//结果以运行类型为主Animal animal = new Dog();animal.cry();animal = new Cat();animal.cry();}}

结果:

dog.cry—小狗汪汪

cat.cry—小猫喵喵

3.多态的使用案例

主人给动物喂食程序

父类:Animalpackage com.fspdu.poly_;public class Animal {private String name;public Animal(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

父类:Foodpackage com.fspdu.poly_;public class Food {private String name;public Food(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}}

子类:Fishpackage com.fspdu.poly_;public class Fish extends Food{public Fish(String name) {super(name);}}

子类:Bonepackage com.fspdu.poly_;public class Bone extends Food{public Bone(String name) {super(name);}}

子类:Catpackage com.fspdu.poly_;public class Cat extends Animal{public Cat(String name) {super(name);}}

子类:Dogpackage com.fspdu.poly_;public class Dog extends Animal{public Dog(String name) {super(name);}}

主人类:Masterpackage com.fspdu.poly_;public class Master {private String name;public Master(String name) {this.name = name;}public String getName() {return name;}public void setName(String name) {this.name = name;}public void feed(Animal animal,Food food){System.out.println(name + "给" + animal.getName() + "吃" + food.getName());}}

main测试package com.fspdu.poly_;public class Poly01 {public static void main(String[] args) {Master tom = new Master("Tom");Dog dog = new Dog("小黑");Bone bone = new Bone("牛骨");tom.feed(dog,bone);Cat cat1 = new Cat("小白");Bone fish = new Bone("鱼骨");tom.feed(cat1,fish);}}

测试结果:

Tom给小黑吃牛骨

Tom给小白吃鱼骨

4.多态注意事项和细节讨论

多态的前提是:两个对象(类)存在继承关系

多态的向上转型

1)本质:父类的引用指向了子类的对象

2)语法:父类类型 引用名 = new 子类类型();

3)特点:

编译类型看左边,运行类型看右边。

可以调用父类中的所有成员(需遵守访问权限),

不能调用子类中特有成员;

最终运行效果看子类的具体实现。

4)案例

父类package com.fspdu.poly_.detail_;public class Animal {String name = "动物";int age = 10;public void sleep(){System.out.println("睡");}public void run(){System.out.println("跑");}public void eat(){System.out.println("吃");}public void show(){System.out.println("hello");}}

子类package com.fspdu.poly_.detail_;public class Cat extends Animal{public void eat(){System.out.println("猫吃鱼");}public void catchMouse(){System.out.println("猫抓老鼠");}}

测试package com.fspdu.poly_.detail_;public class PolyDetail {public static void main(String[] args) {//(向上转型):父类的引用指向了子类的对象//语法:父类类型引用名 = new 子类类型();Animal animal = new Cat();Object obj = new Cat();//可以吗?可以,因为object也是Cat的父类//向上转型调用方法的规则如下://(1)可以调用父类中的所有成员(需要遵守访问权限)//(2)但是不能调用子类的特有的成员//(3)因为在编译阶段,能调用哪些成员,是由编译类型来决定的//animal.catchMouse(); 错误//(4)最终运行效果看子类的具体实现,即调用方法时,按照从子类开始查找方法,然后调用//(5)规则和前面进的方法调用规则一致animal.eat();//猫吃鱼animal.run();//跑animal.show();//helloanimal.sleep();//睡}}

多态的向下转型

1)语法: 子类类型 引用名 = (子类类型) 父类引用;

2)只能强转父类的引用,不能强转父类的对象

3)要求父类的引用必须指向的是当前目标类型的对象

4)可以调用子类类型种所有的成员

案例:

父类与子类和向上转型一样

package com.fspdu.poly_.detail_;public class PolyDetail {public static void main(String[] args) {Animal animal = new Cat();//向下转型Cat cat = (Cat) animal;cat.catchMouse();//猫抓老鼠}}

5.属性没有重写的说法,属性的值看编译类型

package com.fspdu.poly_.detail_;public class PolyDetail02 {public static void main(String[] args) {Base base = new Sub();//向上转型System.out.println(base.count);// 10Sub sub = new Sub();System.out.println(sub.count);// 20}}class Base{int count = 10;}class Sub extends Base{int count = 20;}

6.instanceOf比较操作符

用于判断对象的运行类型是否为XX类型或是XX类型的子类型

package com.fspdu.poly_.detail_;public class PolyDetail03 {public static void main(String[] args) {BB bb = new BB();System.out.println(bb instanceof BB);// trueSystem.out.println(bb instanceof AA);// trueAA aa = new BB();System.out.println(aa instanceof AA);// trueSystem.out.println(aa instanceof BB);// trueObject obj = new Object();System.out.println(obj instanceof AA);//falseString str = "hello";System.out.println(str instanceof Object);//true}}class AA{}class BB extends AA{}

多态的应用

多态数组

数组的定义类型Wie父类类型,里面保存的实际元素类型为子类类型

应用实例:现有一个继承结构如下:要求创建1个Person对象、2个Student对象和2个Teacher对象,统一放在数组中,并调用say方法。

public class PloyArray {public static void main(String[] args) {Person[] person = new Person[5];person[0] = new Person("Jack",20);person[1] = new Student("Jack",18,100);person[2] = new Student("Toom",19,120);person[3] = new Teacher("King",40,18000);person[4] = new Teacher("Qing",50,20000);for (int i = 0; i < person.length; i++) {System.out.println(person[i].say());//动态绑定机制}}}class Person{//父类private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String say(){return name + "\t" + age;}}class Student extends Person{private double score;public Student(String name, int age,double score) {super(name, age);this.score = score;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}@Overridepublic String say() {return super.say() + " score=" + score;}}class Teacher extends Person{private double salary;public Teacher(String name, int age, double salary){super(name, age);this.salary = salary;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}@Overridepublic String say() {return super.say() + " salary=" + salary;}}

Jack 20

Jack 18 score=100.0

Toom 19 score=120.0

King 40 salary=18000.0

Qing 50 salary=20000.0

多态数组(案例升级)

如何调用子类特有的方法,比如Teacher有一个teach,Student有一个study怎么调用?

public class PloyArray {public static void main(String[] args) {Person[] person = new Person[5];person[0] = new Person("Jack",20);person[1] = new Student("Jack",18,100);person[2] = new Student("Toom",19,120);person[3] = new Teacher("King",40,18000);person[4] = new Teacher("Qing",50,20000);for (int i = 0; i < person.length; i++) {System.out.println(person[i].say());//动态绑定机制if(person[i] instanceof Student){//Student student = (Student)person[i];//student.study();((Student)person[i]).study();//向下转型简写} else if (person[i] instanceof Teacher) {((Teacher)person[i]).teach();//向下转型简写}else if(person[i] instanceof Person){}}}}class Person{//父类private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String say(){return name + "\t" + age;}}class Student extends Person{private double score;public Student(String name, int age,double score) {super(name, age);this.score = score;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}@Overridepublic String say() {return super.say() + " score=" + score;}public void study(){System.out.println("学生 " + getName() + "正在学习");}}class Teacher extends Person{private double salary;public Teacher(String name, int age, double salary){super(name, age);this.salary = salary;}public double getSalary() {return salary;}public void setSalary(double salary) {this.salary = salary;}@Overridepublic String say() {return super.say() + " salary=" + salary;}//特有方法public void teach(){System.out.println("老师 " + getName() + "正在授课");}}

Jack 20

Jack 18 score=100.0

学生 Jack正在学习

Toom 19 score=120.0

学生 Toom正在学习

King 40 salary=18000.0

老师 King正在授课

Qing 50 salary=20000.0

老师 Qing正在授课

多态参数

方法定义的形参类型为父类类型,实参类型允许为子类类型

应用实例1:前面的主人给动物喂食

应用实例2:

定义员工类Employee,包含姓名和月工资[private],以及计算年工资getAnnual的方法。普通员工和经理继承了员工,经理类多了奖金bonus属性和管理manage方法,普通员工类多了work方法,普通员工和经理类要求分别重写getAnnual方法

测试类中添加一个方法showEmpAnnal(Employee e),实现获取任何员工对象的年工资,并在main方法中调用该方法[e.getAnnual()]

测试类中添加一个方法,testWork,如果是普通员工,则调用work方法,如果是经理,则调用manage方法

public class PolyParameter {public static void main(String[] args) {Worker tom = new Worker("tom",2500);Manager akl = new Manager("akl", 5000, 200000);PolyParameter polyParameter = new PolyParameter();polyParameter.showEmpAnnual(tom);polyParameter.showEmpAnnual(akl);polyParameter.testWork(tom);polyParameter.testWork(akl);}public void showEmpAnnual(Employee e){System.out.println(e.getAnnual());}public void testWork(Employee e){if(e instanceof Worker){((Worker) e).work();}else if(e instanceof Manager){((Manager) e).manage();}else {System.out.println("不做处理");}}}class Employee{//员工类private String name;private double saraly;public Employee(String name, double saraly) {this.name = name;this.saraly = saraly;}public String getName() {return name;}public void setName(String name) {this.name = name;}public double getSaraly() {return saraly;}public void setSaraly(double saraly) {this.saraly = saraly;}//得到年工资的方法public double getAnnual(){return 12 * saraly;}}class Worker extends Employee{//普通员工子类public Worker(String name, double saraly) {super(name, saraly);}public void work(){System.out.println("普通员工 " + getName() + "正在工作");}@Overridepublic double getAnnual() {return super.getAnnual();}}class Manager extends Employee{//经理子类private double bonus;public Manager(String name, double saraly,double bonus) {super(name, saraly);this.bonus = bonus;}public double getBonus() {return bonus;}public void setBonus(double bonus) {this.bonus = bonus;}public void manage(){System.out.println("经理 " + getName() + "正在管理");}@Overridepublic double getAnnual() {return super.getAnnual() + bonus;}}

30000.0

260000.0

普通员工 tom正在工作

经理 akl正在管理

Java---面向对象编程三大特征【封装 继承 多态】及super关键字 方法重写/覆盖(不定期更新补充)---B站韩顺平老师视频总结

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。