在昨天的ExtendsDemo测试类中,我们如果想要表示多个学生对象,多个老师对象,多个医生对象,则需要使用数组来完成
Student[] students = new Student[3];
students[0] = new Student("小张某", 18, '男', 1001);//创建一个学生类对象
students[1] = new Student("张某", 22, '男', 1002);//创建一个学生类对象
students[2] = new Student("大张某", 25, '男', 1003);//创建一个学生类对象
for (int i = 0; i < students.length; i++) {
students[i].sayHi();
}
Teacher[] teachers = new Teacher[3];
teachers[0] = new Teacher("张X", 31, '男', 999999999);
teachers[1] = new Teacher("闫X", 36, '男', 999999999);
teachers[2] = new Teacher("李X", 30, '男', 999999999);
for (int i = 0; i < teachers.length; i++) {
teachers[i].sayHi();
}
Doctor[] doctors = new Doctor[3];
doctors[0] = new Doctor("李X", 60, '男', 99);
doctors[1] = new Doctor("王X", 50, '男', 99);
doctors[2] = new Doctor("小宇", 40, '女', 99);
for (int i = 0; i < doctors.length; i++) {
doctors[i].sayHi();
}
问题:在测试的代码过程中,因为有三个数组,学生数组,老师数组,医生数组,那么如果需要调用这三个数组中的每个对象的sayHi()。就需要写3个for循环。
解决:把3个数组 用一个数组来表示,基于这些类都有一个父类的情况下才可以。
声明 父类型 new 子对象 的语法就叫做向上造型.
父类型 大 子类型小
好处:一个父类型,可以代表不同的子类型!
class Animal{ //动物类
}
class Tiger extends Animal{ //老虎类
}
main{
类型 对象
Animal a = new Animal();//动物 是 动物 语义通.程序不报错
Tiger t = new Tiger(); //老虎 是 老虎 语义通.程序不报错
Animal a1 = new Tiger(); //老虎 是 动物 语义通.程序不报错
Tiger t1 = new Animal(); //动物 是 老虎 不通,报错
}
//向上造型: 声明父类型 new 子对象
Person[] pp = new Person[9];
pp[0] =new Student("大张三", 58, '男', 1001);
pp[1] =new Student("张三", 38, '男', 1002);
pp[2] =new Student("小张三", 18, '男', 1003);
pp[3] =new Teacher("大李四", 78, '男', 1000000000);
pp[4] =new Teacher("李四", 58, '男', 1000000);
pp[5] =new Teacher("小李四", 48, '男', 10000);
pp[6] =new Doctor("大老王", 60, '男', 38);
pp[7] =new Doctor("老王", 40, '男', 28);
pp[8] =new Doctor("小老王", 20, '男', 18);
for (int i = 0; i < pp.length; i++) {
pp[i].sayHi();
}
问题:运行测试后,当前打印输出的信息不明确,不清楚到底是谁的信息.
解决:可以通过方法的重写来解决.
适用性:当实现继承后,子类无法复用父类中提供的方法时,子类可以通过重写父类的方法,来实现自己的逻辑.
若子类重写实现了父类的方法,在编译期间调用父类的,运行期间执行的则是子类的,具体执行谁看对象是谁!
向上造型的情况下,且子类还实现了重写,才会有调用父执行子的概念.
重写也可以遵循两同两小一大原则.
两同:子类重写父类方法时, 方法名和参数列表 要相同.
两小:子类重写父类方法时,返回值类型等于或小于父类中的那个方法,异常要等于或小于父类中那个方法。
一大:子类重写父类方法时,访问权限要等于或大于父类中的那个方法。
学生类:
void sayHi(){
System.out.println("大家好我叫:" + name + "我的年龄是:" + age + "我的性别" + sex+"学号是"+stuID);
}
老师类:
@Override
void sayHi() {
System.out.println("大家好我叫:" + name + "我的年龄是:" + age + "我的性别" + sex+"工资是"+salary);
}
医生类:
@Override
void sayHi() {
System.out.println("大家好我叫:" + name + "我的年龄是:" + age + "我的性别" + sex+"职称是"+level);
}
-------------
//向上造型: 声明父类型 new 子对象
Person[] pp = new Person[9];
pp[0] =new Student("大张三", 58, '男', 1001);
pp[1] =new Student("张三", 38, '男', 1002);
pp[2] =new Student("小张三", 18, '男', 1003);
pp[3] =new Teacher("大李四", 78, '男', 1000000000);
pp[4] =new Teacher("李四", 58, '男', 1000000);
pp[5] =new Teacher("小李四", 48, '男', 10000);
pp[6] =new Doctor("大老王", 60, '男', 38);
pp[7] =new Doctor("老王", 40, '男', 28);
pp[8] =new Doctor("小老王", 20, '男', 18);
for (int i = 0; i < pp.length; i++) {
//编译期间调用则是父类的方法! 因为受类型制约.
//运行期间调用则是子类的方法! 具体要看对象是谁。
pp[i].sayHi(); //调用父 执行子...
}
定义:接口是一组行为的规范,接口不关心多个类之间是否是一种的关系,只关心多个类之间的行为是否统一。
一个类可以实现多个接口, 所以接口可以多实现。
接口在定义时,一半要求做小而精的接口,不做大而全的接口。
class Aoo{ //类的定义
}
interface Boo{// 接口的定义
}
package oo.day05;
/**
* 接口测试类:
*/
public class InterfaceDemo {
public static void main(String[] args) {
// Aoo a = new Aoo(); 接口是抽象的不能创建对象。
}
}
interface Aoo{ //一个接口的定义
//接口中内容 默认都是公开的!
static final int A = 100; // 常量
abstract void fun(); // 抽象方法
void fun2();
void fun3();
static void fun1(){
} // 可以存放静态方法
}
class super1{//父类
}
interface Doo{
void test();//抽象方法
}
interface Coo extends Doo{
}
class Boo extends super1 implements Aoo,Coo{ //一个类实现多个接口 接口名之间用逗号隔开。
@Override
public void fun() {
}
@Override
public void fun2() {
}
@Override
public void fun3() {
}
@Override
public void test() {
}
}
/***
* 类 与 类 之间 可以实现继承关系
* 接口 与 接口之间 可以实现继承关系 : 可以通过继承得到代码上的内容
*
* 类 与 接口 直接 只能是实现关系 :类需要重写实现接口中所有抽象内容
*/
人类的对象在睡觉的行为上实现多态:有的人右侧睡,有的人左侧睡,有的人平躺着睡....
在程序中的多态指的是一个父类的行为 子类有不同的逻辑实现.
人类 r1 = new 理发师();//向上造型 声明父 new 子
人类 r2 = new 医生类();
人类 r3 = new 园丁类();
r1.cut();//编译期调用父 运行期执行理发师对象的cut行为
r2.cut();//编译期调用父 运行期执行医生类对象的cut行为
r3.cut();//编译期调用父 运行期执行园丁类对象的cut行为
class 人类{
void cut(){ }
}
class 理发师 extedns 人类 {
void cut(){
sout("剪发");
}
}
class 医生类 extedns 人类{
void cut(){
sout("手术");
}
}
class 园丁类 extedns 人类{
void cut(){
sout("剪草");
}
}
我 w = new 我();
w. 授课();
w. 互相卷();
讲师 j = new 我(); //向上造型
j.授课行为();
其它老师同事 q = new 我();
q.互相卷();
interface 讲师{
授课();
}
interface 其它老师同事{
互相卷();
}
class 我 implments 讲师, 其它老师同事{
授课(){ }
互相卷(){ }
}
父 大 子 小 ------ 声明父 类型 = new 子对象();
能够向上造型 例如: 父 new 子 , 接口 new 实现类
能否强转成功,要看对应下面的条件:
条件一:要强转的引用类型变量中的对象 就是要转换的这个类型
条件二: 要强转的引用类型变量中的对象 实现了要转换的这个接口类型.
子类或实现类之间,是无法互相转换的!!
在引用类型转换的工作之前,应该使用 instanceOf 关键字 来判断是否可以强转成功.
main{
Aoo a1 = new Boo();//声明父 new 子
Boo b1 = (Boo)a1;//强转成功,符合条件一 强转语法:在需要强转的变量前写一组小括号(要转换的类型)
Inter1 i1 = (Inter1)a1;//强转成功, 符合条件二
Coo c1 = (Coo)a1;// 报错 ....类型转换失败异常
}
class Aoo{//父类
}
interface Inter1{//接口
}
class Boo extends Aoo implements Inter1{ // 子类
}
class Coo extends Aoo{
}
---
package oo.day06;
/**
* 类型转换的使用演示类:
* 能否强转成功,要看对应下面的条件:
条件一:要强转的引用类型变量中的对象 就是要转换的这个类型
条件二: 要强转的引用类型变量中的对象 实现了要转换的这个接口类型.
*/
public class ClassCastDemo {
public static void main(String[] args) {
Aoo a1 = new Boo();//向上造型
if(a1 instanceof Boo){ //判断a1中的对象 是否是 Boo类型
Boo b1 = (Boo)a1;//可以强转完成 符合条件一
}
if(a1 instanceof Inter1){//判断a1中的对象 是否实现了 Inter1接口
Inter1 i1 = (Inter1) a1; //可以强转完成 符合条件二
}
if(a1 instanceof Coo){
Coo c1 = (Coo) a1;//运行时异常: class cast Exception 类型转换异常!
}else {
System.out.println("a1不是Coo类型,强转失败!");
}
//在引用类型转换的工作之前,应该使用 instanceOf 关键字 来判断是否可以强转成功.
}
}
class Aoo{//父类
}
interface Inter1{//接口
}
class Boo extends Aoo implements Inter1{ // 子类
}
class Coo extends Aoo{
}
上篇文章:入门Java编程的知识点—>继承(day09)-CSDN博客https://blog.csdn.net/Z0412_J0103/article/details/141464638下篇文章: 入门Java编程的知识点—>静态方法(day11)-CSDN博客https://blog.csdn.net/Z0412_J0103/article/details/141550201