eleven接口、多态
能够写出接口的定义格式
public interface 接口名 {
public static final 数据类型 名称 = 数据值;
//抽象方法: 必须使用实现类对象调用
void method();
//默认方法: 必须使用实现类对象调用
public default void show() {...}
//静态方法: 必须使用接口名调用
public static void fun(){...}
}
能够写出接口的实现格式
public class 类名 implements 接口名 {
//覆盖重写所有的抽象方法
//静态方法不存在覆盖重写
//默认方法可以选择性的覆盖重写,必须去掉default关键字
}
能够说出接口中的成员特点
能够说出多态的前提
1.必须要有继承/接口实现
2.必须要有父类引用指向子类对象(父类/接口类型的变量 保存 子类/实现类对象的地址值)
3.必须要有方法的覆盖重写,否则失去多态的意义
能够写出多态的格式
父类类型 对象名称 = 子类对象;
接口类型 对象名称 = 实现类对象;
能够理解多态向上转型和向下转型
向上转型:
多态的本质就是向上转型 把子类对象当成父类类型使用
//Animal a = new Dog();//转型之后只能调用父类中的规定的方法
Animal a = new Cat();//转型之后只能调用父类中的规定的方法
向下转型: 把子类对象转换成子类自己的类型
转后类型 对象名 = (转后类型)转前变量;
Dog dog = (Dog)a;
判断类型: instanceof
a instanceof Dog: 判断引用变量a如果保存的是Dog类型的对象,返回true,否则返回false
接口、多态
今日内容介绍
接口 多态
第一章 接口
1.1 接口的概念【重点】
1.概念:对外暴露的规则/规范/标准,只要符合该规则/规范/标准的东西都可以使用2.接口,是Java语言中一种引用类型,编译后也有对应的class文件,是方法的汇总 3.作用: 实现对类的功能的扩展,解决java中类的单继承的局限性
1.2 接口中可以定义的内容【重点】
1.抽象方法: public abstract 返回值类型 方法名称(形式参数列表...); 2.默认方法【jdk8开始】: public default 返回值类型 方法名称(形式参数列表...) {...} 3.静态方法【jdk8开始】: public static 返回值类型 方法名称(形式参数列表...) {...} 4.常量: public staitc final 数据类型 变量名称 = 数据值;注意:接口在设计之初,目的只是为了制定一套规则/规范/标准,所以设计之初接口中只能定义抽象方法和常量必须要掌握接口的定义格式和接口中抽象方法的定义和使用格式【最重要】
1.3 接口的定义格式【重点】
类的定义格式【复习】public class 类名 {//成员变量//成员方法//构造方法//静态方法 } 接口的定义格式public interface 类名 {//常量//抽象方法//默认方法//静态方法 }
1.4 接口中抽象方法的定义格式和使用【重点】
/*1.接口中抽象方法的定义格式public abstract 返回值类型 方法名称(形式参数列表...);注意:(1)和以前定义方法格式相同,但是需要去掉{},添加abstract(2)返回值类型和参数列表根据需求确定(3)接口中抽象方法,有默认修饰符public abstract,不写也有抽象类中抽象方法必须写public abstract,不能省略 2.接口中抽象方法的使用(1)不能直接创建接口的对象(2)定义实现类 实现 接口 关键字 implements格式:public class 类名 implements 接口A,接口B {//覆盖重写接口中的所有的抽象方法}(3)实现类中覆盖重写接口中的所有的抽象方法去掉abstract关键字,添加{}快捷键: ctrl + i(4)创建实现类对象(5)使用实现类对象调用方法 */ //USB接口 public interface USB {//抽象方法//开启功能public abstract void open();//抽象方法: public abstract 是默认修饰符,可以省略//关闭功能void close(); }
//USB接口实现类U盘 public class UDisk implements USB {@Overridepublic void open() {System.out.println("U盘已经开启....");}@Overridepublic void close() {System.out.println("U盘已经关闭....");} }
//USB接口实现类扫描仪 public class HMScanner implements USB {@Overridepublic void open() {System.out.println("扫描仪已经打开...");}@Overridepublic void close() {System.out.println("扫描仪已经关闭...");} }
//测试类 public class Demo01Inter {public static void main(String[] args) {//创建实现类对象UDisk uDisk = new UDisk();//实现类对象调用成员方法uDisk.open();uDisk.close();System.out.println("=================="); //创建实现类对象HMScanner hmScanner = new HMScanner();//实现类对象调用成员方法hmScanner.open();hmScanner.close();} }
1.5 接口中默认方法的定义格式和使用【了解】
/*接口中默认方法的定义格式和使用问题:定义接口后,有很多实现类在使用接口,如果对接口功能升级添加了新的抽象方法导致所有的实现类必须修改代码,太麻烦解决方案: 默认方法默认方法的定义格式:public default 返回值类型 方法名称(形式参数列表...){//方法体;}默认方法的使用: 只能使用实现类对象调用默认方法注意:1.接口中的默认方法,不强制要求实现类进行覆盖重写2.但是实现类可以根据需求,选择性的覆盖重写接口中的默认方法3.如果实现类覆盖重写接口中的默认方法,必须去掉default关键字 */ //定义接口 //USB接口 public interface USB {//抽象方法//开启功能public abstract void open();//抽象方法: public abstract 是默认修饰符,可以省略//关闭功能void close();//默认方法public default void driver() {System.out.println("USB接口提供的默认驱动程序....");} }
//USB接口实现类U盘 public class UDisk implements USB {@Overridepublic void open() {System.out.println("U盘已经开启....");}@Overridepublic void close() {System.out.println("U盘已经关闭....");}//该实现类发现接口中的默认方法可以满足需求,就不需要重写 }
//USB接口实现类扫描仪 public class HMScanner implements USB {@Overridepublic void open() {System.out.println("扫描仪已经打开...");}@Overridepublic void close() {System.out.println("扫描仪已经关闭...");}//该实现类发现接口中的默认方法无法满足需求,进行了覆盖重写@Overridepublic void driver() {System.out.println("使用扫描仪专用驱动");} }
public class Demo01Inter {public static void main(String[] args) {//创建实现类对象UDisk uDisk = new UDisk();//实现类对象调用成员方法uDisk.open();uDisk.close();//实现类对象调用默认方法uDisk.driver();System.out.println("==================");//创建实现类对象HMScanner hmScanner = new HMScanner();//实现类对象调用成员方法hmScanner.open();hmScanner.close();//实现类对象调用默认方法hmScanner.driver(); } }
1.6 接口中的静态方法的定义和使用【了解】
/*1.定义格式public static 返回值类型 方法名称(形式参数列表...) {方法体;}2.使用格式: 只能使用接口名称调用接口中的静态方法3.注意:(1)接口中的静态方法,属于接口本身,与实现类无关,在实现类中不存在覆盖重写(2)类中的静态方法,属于类本身,与接口无关,与对象无关(3)类中的静态方法:名直接调用 ---推荐使用对象直接调用 ---不推荐使用总结: 静态的内容要么用接口名称调用,要么用类名称调用 */ //USB接口 public interface USB {//抽象方法//开启功能public abstract void open();//抽象方法: public abstract 是默认修饰符,可以省略//关闭功能void close();//默认方法public default void driver() {System.out.println("USB接口提供的默认驱动程序....");}//静态方法public static void thanks() {System.out.println("感谢使用USB接口....");} }
//USB接口实现类U盘 public class UDisk implements USB {@Overridepublic void open() {System.out.println("U盘已经开启....");}@Overridepublic void close() {System.out.println("U盘已经关闭....");} //静态方法public static void thanks() {System.out.println("感谢使用U盘....");} }
//USB接口实现类扫描仪 public class HMScanner implements USB {@Overridepublic void open() {System.out.println("扫描仪已经打开...");}@Overridepublic void close() {System.out.println("扫描仪已经关闭...");}@Overridepublic void driver() {System.out.println("使用扫描仪专用驱动");} //静态方法public static void thanks() {System.out.println("感谢使用扫描仪....");} }
public class Demo {public static void main(String[] args) {//创建实现类对象UDisk uDisk = new UDisk();//实现类对象调用成员方法uDisk.open();uDisk.close();//实现类对象调用默认方法uDisk.driver();//实现类名称调用静态方法UDisk.thanks();//接口名称调用静态方法USB.thanks();System.out.println("==================");//创建实现类对象HMScanner hmScanner = new HMScanner();//实现类对象调用成员方法hmScanner.open();hmScanner.close();//实现类对象调用默认方法hmScanner.driver();//实现类名称调用静态方法HMScanner.thanks();//接口名称调用静态方法USB.thanks();} }
1.7 接口中成员变量的使用【了解】
/*接口中成员变量的使用接口中定义的变量,都是常量(值不可以改变)默认修饰符public static final 不写也有接口中常量默认值认为是无效的必须显式赋值接口中的常量的使用: 接口名称.常量名称建议: 接口中常量的命名全部使用大写字母,单词之间用_分隔 */ /*USB接口接口中不能定义变量,只能定义常量,而且常量有默认修饰符public static final接口中的常量默认值认为是无效的,必须显式赋值常量建议全部使用大写字母,单词之间使用_分隔*/ public interface USB {//版本public static final double VERSION = 3.0;//版本public static final int MAX_SPEED_OF_TRANSFER = 500;//最大传输速度//静态方法: 展示USB接口的相关信息public static void show() {System.out.println("USB接口版本: " + VERSION + ", 最大传输速度: " + MAX_SPEED_OF_TRANSFER + "MB/s");//show方法和内部输出的常量,都在USB接口中,所以可以省略接口名System.out.println("USB接口版本: " + USB.VERSION + ", 最大传输速度: " + USB.MAX_SPEED_OF_TRANSFER + "MB/s");}//前面定义好的其它方法省略了... }
/*接口中成员变量的使用接口中定义的变量,都是常量(值不可以改变)默认修饰符public static final 不写也有接口中常量默认值认为是无效的必须显式赋值接口中的常量的使用: 接口名称.常量名称建议: 接口中常量的命名全部使用大写字母,单词之间用_分隔 */ public class Demo04InterConstant {public static void main(String[] args) {//调用接口中的静态方法USB.show();System.out.println("--------");//直接输出接口中的常量System.out.println("USB接口版本: " + USB.VERSION);System.out.println("USB接口最大传输速度: " + USB.MAX_SPEED_OF_TRANSFER);} }
1.8 接口的多实现【重点】
/*接口的多实现在继承体系中,一个类只能继承一个父类【类的单继承: 亲爹只能有一个】。对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现【类实现接口的多实现: 干爹可以有多个】。并且,一个类能继承一个父类,同时实现多个接口。一个类能继承一个父类,同时实现多个接口格式:public class 子类名 extends 父类名 implements 接口名A,接口名B {覆盖重写抽象父类和接口中的所有的抽象方法}实现步骤:1.创建抽象父类AbstractClass,内部定义抽象方法2.创建接口MyInterA和MyInterB,内部定义抽象方法3.创建子类MyClass 继承 抽象父类AbstractClass 实现接口 MyInterA和MyInterB4.子类MyClass 覆盖重写抽象父类和接口中的所有的抽象方法5.创建子类MyClass的对象6.使用子类MyClass的对象调用方法注意:子类必须重写父类和接口中的所有抽象方法,只要有一个抽象方法没有被重写,该子类必须定义为抽象类,看MyClass02类 */
//创建抽象父类AbstractClass,内部定义抽象方法 public abstract class AbstractClass {//抽象方法public abstract void method(); }
//2.创建接口MyInterA内部定义抽象方法 public interface MyInterA {//抽象方法void show(); }
//2.创建接口MyInterB内部定义抽象方法 public interface MyInterB {//抽象方法void fun(); }
//3.创建子类MyClass 继承 抽象父类AbstractClass 实现接口 MyInterA和MyInterB public class MyClass extends AbstractClass implements MyInterA, MyInterB {//4.子类MyClass 覆盖重写抽象父类和接口中的所有的抽象方法@Overridepublic void method() {System.out.println("MyClass...method...");}@Overridepublic void show() {System.out.println("MyClass...show...");}@Overridepublic void fun() {System.out.println("MyClass...fun...");} }
/*接口的多实现在继承体系中,一个类只能继承一个父类【类的单继承: 亲爹只能有一个】。对于接口而言,一个类是可以实现多个接口的,这叫做接口的多实现【类实现接口的多实现: 干爹可以有多个】。并且,一个类能继承一个父类,同时实现多个接口。一个类能继承一个父类,同时实现多个接口格式:public class 子类名 extends 父类名 implements 接口名A,接口名B {覆盖重写抽象父类和接口中的所有的抽象方法}实现步骤:1.创建抽象父类AbstractClass,内部定义抽象方法2.创建接口MyInterA和MyInterB,内部定义抽象方法3.创建子类MyClass 继承 抽象父类AbstractClass 实现接口 MyInterA和MyInterB4.子类MyClass 覆盖重写抽象父类和接口中的所有的抽象方法5.创建子类MyClass的对象6.使用子类MyClass的对象调用方法注意:子类必须重写父类和接口中的所有抽象方法,只要有一个抽象方法没有被重写,该子类必须定义为抽象类,看MyClass02类 */ public class Demo02InterNotice {public static void main(String[] args) {//5.创建子类MyClass的对象MyClass myClass = new MyClass();//6.使用子类MyClass的对象调用方法myClass.method();myClass.show();myClass.fun();} }
/*子类继承父类 实现多个接口时,必须覆盖重写所有抽象方法,只要有一个抽象方法没有被重写,该子类必须定义为抽象类*/ public abstract class MyClass02 extends AbstractClass implements MyInterA,MyInterB {@Overridepublic void method() {System.out.println("MyClass02...method...");}@Overridepublic void show() {System.out.println("MyClass02...show...");}/*@Overridepublic void fun() {System.out.println("MyClass02...fun...");}*/ }
1.9 接口的多继承关系【了解】
接口的多继承关系子接口会拥有父接口中的所有抽象方法
public interface MyInter03A {//抽象方法void a(); }
public interface MyInter03B {//抽象方法void b(); }
public interface MyInter03C {//抽象方法void c(); }
/*接口可以多继承,子接口自动拥有父接口中的所有抽象方法*/ public interface MyInter03D extends MyInter03A, MyInter03B, MyInter03C {//抽象方法/*抽象方法a,b,c分别已经在其它接口中定义好了,此处没有必要重新定义了,只需要继承其它接口*///void a();//void b();//void c();void d(); }
public class MyInter03DImpl implements MyInter03D {@Overridepublic void a() {System.out.println("MyInter03DImpl...a...");}@Overridepublic void b() {System.out.println("MyInter03DImpl...b...");}@Overridepublic void c() {System.out.println("MyInter03DImpl...c...");}@Overridepublic void d() {System.out.println("MyInter03DImpl...d...");} }
/*接口的多继承关系子接口会拥有父接口中的所有抽象方法*/ public class Demo03Inter {public static void main(String[] args) {//创建接口实现类对象MyInter03DImpl myInter03D = new MyInter03DImpl();//调用成员方法myInter03D.a();myInter03D.b();myInter03D.c();myInter03D.d();} }
第二章 多态
2.1 生活中的多态【重点】
/*面向对象的三大特征: 封装,继承,多态封装: 提高代码的安全性继承: 提高代码的复用性多态: 提高代码的扩展性多态的概念:同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。简单的理解: 同一个事物,表现出来不同的形态举个栗子:比如说你自己在学校中: 是一个学生在餐馆中: 是一个顾客在公司中: 是一个员工在你家里: 是妻子/丈夫回老家: 是一个孩子比如说H2O:在常温下: 是液体在高温下: 是水蒸气在低温下: 是固体冰 */
2.2 多态中的代码体现【重点】
/*多态中的代码体现1.概念:同一行为,通过不同的事物,可以体现出来的不同的形态。多态,描述的就是这样的状态。java中的多态: 指的是对象具备多态性2.举例:假设学生Student类是人Person类的子类学生 是 一个学生 //不是多态 左侧是Student类型,右侧是Student对象,左右一致Student stu = new Student();学生 是 一个人//是多态 左侧是Person类型,右侧是Student对象,左右不一致,左边是父类,右边是子类对象Person p = new Student();3.多态的前提:(1)必须要有继承或者接口实现(2)必须要有父类引用指向子类对象(父类类型的变量保存子类对象的地址值)(3)必须要有方法的覆盖重写,否则将失去多态的意义4.多态的本质(1)就是把子类对象当成父类类型使用父类引用指向子类对象(父类类型的变量保存子类对象的地址值)(2)多态的方式调用方法,方法跟着对象走 */ //定义父类 public class Person {//吃饭public void eat() {System.out.println("人吃饭...");} }//定义子类 public class Student extends Person {@Overridepublic void eat() {System.out.println("学生时间比较紧张,吃点快餐,抓紧回去学习....");} }//定义子类 public class Teacher extends Person {@Overridepublic void eat() {System.out.println("老师上课很辛苦,吃点好的,补一补...");} } //测试类 public class Demo01DuoTai {public static void main(String[] args) {//不是多态:左侧是Student类型,右侧是Student对象,左右一致Student stu = new Student();stu.eat();System.out.println("----------");//多态的方式创建Student类的对象//Person类型变量保存子类Student类型的对象Person p = new Student();p.eat();//Person类型变量保存子类Teacher类型的对象p = new Teacher();p.eat();} }
2.3 多态中成员方法的访问特点【重点】
//编译时期看左边(父类/接口),运行时期看右边(子类/实现类) //定义抽象父类Animal02 public abstract class Animal02 {//抽象方法public abstract void eat();//吃public abstract void sleep();//睡 } //定义子类Dog02 继承 抽象父类Animal02 public class Dog02 extends Animal02 {@Overridepublic void eat() {System.out.println("狗吃骨头...");}@Overridepublic void sleep() {System.out.println("小狗在眯着眼睡...");}//特有功能public void kanHome() {System.out.println("小狗在看家....");} } //测试类 public class Demo02DuoTai {public static void main(String[] args) {//多态的方式创建Animal02的对象Animal02 a = new Dog02();//调用成员方法/*在多态中把Dog02对象(子类对象)当成Animal02类型(父类)使用,此时Dog02对象表现的是父类Animal02的形态多态的方式调用eat方法编译时期: 检测父类Animal02中是否有eat方法的定义发现父类中: 有eat方法的定义,编译通过运行时期: 运行的是Dog02类中重写后的eat方法*/a.eat();/*在多态中把Dog02对象(子类对象)当成Animal02类型(父类)使用,此时Dog02对象表现的是父类Animal02的形态多态的方式调用sleep方法编译时期: 检测父类Animal02中是否有sleep方法的定义发现父类中: 有sleep方法的定义,编译通过运行时期: 运行的是Dog02类中重写后的sleep方法*/a.sleep();/*在多态中把Dog02对象(子类对象)当成Animal02类型(父类)使用,此时Dog02对象表现的是父类Animal02的形态多态的方式调用kanHome方法编译时期: 检测父类Animal02中是否有kanHome方法的定义发现父类中: 没有kanHome方法的定义,编译报错*///a.kanHome();} }
2.4 多态的好处和弊端
/*多态的好处和弊端不使用多态:好处: 可以调用子类的特有行为弊端: 扩展性极差使用多态:好处: 扩展性强弊端: 不可以调用子类的特有行为 */ //测试代码 public class Demo03DuoTai {public static void main(String[] args) {//不使用多态Dog dog = new Dog();//调用成员方法dog.eat();dog.kanHome();dog.sleep();//错误: 左右两边类型不匹配//dog = new Cat();System.out.println("----------");//使用多态Animal a = new Dog();a.eat();a.sleep();/*在多态中是把Dog对象当成父类Animal类型使用,此时Dog对象表现的是父类Animal的形态多态(父类变量)调用kanHome方法编译时期: 检测父类Animal中是否有kanHome方法的定义发现父类中: 没有kanHome方法的定义,编译失败(报错了)*///a.kanHome();//重新把Cat对象保存到父类Animal变量a中a = new Cat();a.eat();a.sleep();/*在多态中是把Cat对象当成父类Animal类型使用,此时Cat对象表现的是父类Animal的形态多态(父类变量)调用catchMouse方法编译时期: 检测父类Animal中是否有catchMouse方法的定义发现父类中: 没有catchMouse方法的定义,编译失败(报错了)*///a.catchMouse();} }
/*多态的好处:可以使用父类/接口,作为方法的参数,提高方法的扩展性问题:下面分别是用Animal的子类Dog和Cat作为方法参数,定义了两个方法Animal的子类可以有任意多个,这样定义的方法也就会有任意多个每创建一个子类,就得再添加一个方法,太麻烦解决方案:所有的子类对象,都可以当做父类类型使用所以可以使用父类类型作为方法的参数类作为方法的参数:调用方法时,传递的是该类的对象或者是该类的子类对象类的数据体现形式是对象抽象类的数据体现形式是子类对象接口的数据体现形式是实现类对象暴露新的问题: 方法内部不能直接调用子类的特有行为了(后面解决) */ //测试类 public class Demo04DuoTai {public static void main(String[] args) {//创建Dog类型的对象Dog dog = new Dog();//调用showDog传递Dog类型的对象dogshowDog(dog);System.out.println("----------------");//创建Cat类型的对象Cat cat = new Cat();//调用showCat传递Cat类型的对象catshowCat(cat);}//定义方法,参数是Dog类型public static void showDog(Dog dog) {dog.eat();dog.kanHome();dog.sleep();}//定义方法,参数是Cat类型public static void showCat(Cat cat) {cat.eat();cat.catchMouse();cat.sleep();} } //测试类 public class Demo05DuoTai {public static void main(String[] args) {//创建Dog类型的对象Dog dog = new Dog();//调用showAnimal传递Dog类型的对象dogshowAnimal(dog);System.out.println("----------------");//创建Cat类型的对象Cat cat = new Cat();//调用showAnimal传递Cat类型的对象catshowAnimal(cat);}//定义方法,参数是Animal类型public static void showAnimal(Animal a) {a.eat();a.sleep();//错误: 你传递的所有对象都被当成Animal类型使用//然而Animal类型中没有定义kanHome和catchMouse方法//a.kanHome();//a.catchMouse();}}
2.6 多态中的向上向下转型
/*多态中的向上转型多态的本质(父类引用指向子类对象): 就是向上转型类似于 基本类型的自动类型转换取值范围小的数据或者变量可以直接赋值给取值范围大的变量int a = 100;//int: 占4个字节double d = a;//double: 占8个字节不需要进行特殊的处理多态中的向下转型类似于 基本类型的强制类型转换取值范围大的数据或者变量不可以直接赋值给取值范围小的变量double d2 = 100;//double: 占8个字节int c = (int)d2;//int: 占4个字节强制类型转换:转后类型 对象名称 = (转后类型)转前的对象或者变量名称; 注意:多态的向下转型(强制类型转换)存在安全隐患如果转换前的类型和转换后的类型不一致,就会报出类型转换异常(ClassCastException)如何解决这个问题呢? */ public class Demo06DuoTai {public static void main(String[] args) {//多态的方式创建Animal类型的对象: 向上转型Animal a = new Dog();//此时只能直接调用Animal中规定好的方法a.eat();a.sleep();/*在多态中是把Dog对象当成父类Animal类型使用,此时Dog对象表现的是父类Animal的形态多态(父类变量)调用kanHome方法编译时期: 检测父类Animal中是否有kanHome方法的定义发现父类中: 没有kanHome方法的定义,编译失败(报错了)*///a.kanHome();//把Cat对象重新存储到Animal变量中a = new Cat();//向下转型: 把Animal类型的变量a,强制转换成Dog类型Dog dog = (Dog)a;//就可以调用Dog类的特有行为了dog.kanHome();} }
2.7 instanceof关键字
/*强制类型转换(向下转型)存在安全隐患:如果转后类型和创建对象的具体类型不一致,报出类型转换异常 ClassCastException如何解决呢?如果变量a指向的是Dog类型,把Animal类型的变量a强制转换成Dog类型如果变量a指向的是Cat类型,把Animal类型的变量b强制转换成Cat类型如何判断变量a指向的到底是哪种类型的对象呢?使用instanceof关键字使用格式:boolean result = 对象名 instanceof 类名如果对象名称中保存的是该类的对象,返回true。如果对象名称中保存的不是该类的对象,返回false。 */
//测试类 public class Demo07DuoTai {public static void main(String[] args) {//多态的方式创建Animal类型的对象: 向上转型//Animal a = new Dog();Animal a = new Cat();//此时只能直接调用Animal中规定好的方法a.eat();a.sleep();//如果引用变量a存储的是Dog类型的变量if (a instanceof Dog) {//向下转型: 把Animal类型的变量a,强制转换成Dog类型Dog dog = (Dog)a;//就可以调用Dog类的特有行为了dog.kanHome();}//如果引用变量a存储的是Cat类型的变量if (a instanceof Cat) {//向下转型: 把Animal类型的变量a,强制转换成Cat类型Cat cat = (Cat)a;//就可以调用Cat类的特有行为了cat.catchMouse();}} } /*测试类类作为方法的参数:调用方法时,传递的是该类的对象或者是该类的子类对象类的数据体现形式是对象抽象类的数据体现形式是子类对象接口的数据体现形式是实现类对象暴露新的问题: 方法内部不能直接调用子类的特有行为了解决方案: 使用instanceof + 向下转型 */ public class Demo08DuoTai {public static void main(String[] args) {//创建Dog类型的对象Dog dog = new Dog();//调用showAnimal传递Dog类型的对象dogshowAnimal(dog);System.out.println("----------------");//创建Cat类型的对象Cat cat = new Cat();//调用showAnimal传递Cat类型的对象catshowAnimal(cat);}//定义方法,参数是Animal类型public static void showAnimal(Animal a) {a.eat();a.sleep();//如果引用变量a存储的是Dog类型的变量if (a instanceof Dog) {//向下转型: 把Animal类型的变量a,强制转换成Dog类型Dog dog = (Dog)a;//就可以调用Dog类的特有行为了dog.kanHome();}//如果引用变量a存储的是Cat类型的变量if (a instanceof Cat) {//向下转型: 把Animal类型的变量a,强制转换成Cat类型Cat cat = (Cat)a;//就可以调用Cat类的特有行为了cat.catchMouse();}} }
第三章 综合案例1--笔记本案例【重点】
3.1 笔记本综合案例分析
定义笔记本类,具备开机,关机和使用USB设备的功能。具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。 鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用; 进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘USB接口,包含开启功能、关闭功能 笔记本类,包含运行功能、关机功能、使用USB设备功能 鼠标类,要符合USB接口 键盘类,要符合USB接口
3.2 笔记本综合案例实现步骤分析
1.定义USB接口抽象方法: 开启功能,关闭功能 2.定义笔记本Computer类成员方法: 开机功能,使用USB接口的功能,关机功能 3.定义鼠标Mouse类 实现 USB接口(1)覆盖重写抽象方法:开启功能,关闭功能(2)定义特有方法: 点击鼠标功能 4.定义键盘KeyBoard类 实现 USB接口(1)覆盖重写抽象方法:开启功能,关闭功能(2)定义特有方法: 敲击功能 5.测试类(1)创建笔记本Computer类的对象(2)创建外部设备鼠标Mouse类的对象(3)创建外部设备键盘KeyBoard类的对象(4)笔记本Computer类的对象调用开机功能(5)笔记本Computer类的对象调用使用USB接口的功能,传递外部设备鼠标Mouse类的对象(6)笔记本Computer类的对象调用使用USB接口的功能,传递外部设备键盘KeyBoard类的对象(7)笔记本Computer类的对象调用关机功能
3.3 笔记本综合案例代码实现
/*1.定义USB接口抽象方法: 开启功能,关闭功能*/ public interface USB {//抽象方法: 开启功能public abstract void open();//抽象方法: 关闭功能public abstract void close(); } /*2.定义笔记本Computer类成员方法: 开机功能,使用USB接口的功能,关机功能*/ public class Computer {//成员方法: 开机功能public void powerOn() {System.out.println("开机....");}/*//下面的定义方式不好,因为有多少外部设备就得定义多少方法//但是所有的外部设备都可以当成USB接口使用//可以定义方法使用USB接口作为参数//成员方法: 使用鼠标Mouse的功能public void useMouse(Mouse mouse) {}//成员方法: 使用键盘KeyBoard的功能public void useMouse(KeyBoard keyBoard) {}*///成员方法: 使用USB接口的功能/*方法被调用时:USB usb = 0x666 = new Mouse();//多态*/public void useUSB(USB usb) {//传递进来的所有外部设备都当成USB接口使用//只能直接调用USB接口中规定的方法//调用开启设备的功能usb.open();//想调用特有方法,必须进行强制类型转换//判断如果usb变量中保存的是Mouse类的对象if (usb instanceof Mouse) {//把USB类型的变量usb,强制转换成Mouse类型的变量Mouse mouse = (Mouse)usb;//调用点击鼠标的功能mouse.click();}//判断如果usb变量中保存的是KeyBoard类的对象if (usb instanceof KeyBoard) {//把USB类型的变量usb,强制转换成KeyBoard类型的变量KeyBoard keyBoard = (KeyBoard)usb;//调用敲击键盘的功能keyBoard.type();}//调用关闭设备的功能usb.close();}//成员方法: 关机功能public void powerOff() {System.out.println("关机...");} } /*3.定义鼠标Mouse类 实现 USB接口(1)覆盖重写抽象方法:开启功能,关闭功能(2)定义特有方法: 点击鼠标功能*/ public class Mouse implements USB {//(1)覆盖重写抽象方法:开启功能@Overridepublic void open() {System.out.println("鼠标开启,红灯闪闪...");}//(1)覆盖重写抽象方法:关闭功能@Overridepublic void close() {System.out.println("鼠标关闭,红灯闪闪...");}//(2)定义特有方法: 点击鼠标功能public void click() {System.out.println("点击鼠标,打开文件...");} } /*4.定义键盘KeyBoard类 实现 USB接口(1)覆盖重写抽象方法:开启功能,关闭功能(2)定义特有方法: 敲击功能*/ public class KeyBoard implements USB{//(1)覆盖重写抽象方法:开启功能@Overridepublic void open() {System.out.println("键盘开启,绿灯闪闪...");}//(1)覆盖重写抽象方法:关闭功能@Overridepublic void close() {System.out.println("键盘关闭,绿灯闪闪...");}//(2)定义特有方法: 敲击功能public void type() {System.out.println("敲击键盘,向文件中写内容...");} } //测试类 public class Demo03Computer {public static void main(String[] args) {//(1)创建笔记本Computer类的对象Computer computer = new Computer();//(2)创建外部设备鼠标Mouse类的对象Mouse mouse = new Mouse();//假设地址值: 0x666//(3)创建外部设备键盘KeyBoard类的对象KeyBoard keyBoard = new KeyBoard();//(4)笔记本Computer类的对象调用开机功能computer.powerOn();//(5)笔记本Computer类的对象调用使用USB接口的功能,传递外部设备鼠标Mouse类的对象//调用方法: computer.useUSB(0x666)computer.useUSB(mouse);//(6)笔记本Computer类的对象调用使用USB接口的功能,传递外部设备键盘KeyBoard类的对象computer.useUSB(keyBoard);//(7)笔记本Computer类的对象调用关机功能computer.powerOff();} }
相关文章:
eleven接口、多态
能够写出接口的定义格式 public interface 接口名 { public static final 数据类型 名称 数据值; //抽象方法: 必须使用实现类对象调用 void method(); //默认方法: 必须使用实现类对象调用 public default void show() {...} …...

重磅惊喜!OpenAI突然上线GPT-4o超长输出模型!「Her」高级语音模式已开放测试
在最近的大模型战争中,OpenAI似乎很难维持霸主地位。虽然没有具体的数据统计,但Claude3.5出现后,只是看网友们的评论,就能感觉到OpenAI订阅用户的流失: Claude3.5比GPT-4o好用,为什么我们不去订阅Claude呢&…...
解决问题 CUDA error: CUBLAS_STATUS_INVALID_VALUE when calling `cublasGemmEx
遇到问题如下: Traceback (most recent call last):File "run_warmup_a.py", line 431, in <module>main()File "run_warmup_a.py", line 142, in mainreturn main_worker(args, logger)File "run_warmup_a.py", line 207, in…...
【Python实战因果推断】67_图因果模型2
目录 Are Consultants Worth It? Crash Course in Graphical Models Chains Are Consultants Worth It? 为了展示有向无环图(DAG)的力量,让我们考虑一个更有趣但处理因素并未随机化的情况。假设你是某公司的经理,正在考虑是否聘请顶级咨询顾问。你…...

RK3588+MIPI+GMSL+AI摄像机:自动车载4/8通道GMSL采集/边缘计算盒解决方案
RK3588作为目前市面能买到的最强国产SOC,有强大的硬件配置。在智能汽车飞速发展,对图像数据矿场要求越来越多的环境下,如何高效采集数据,或者运行AI应用,成为刚需。 推出的4/8通道GMSL采集/边缘计算盒产品满足这些需求…...

智云-一个抓取web流量的轻量级蜜罐
智云-一个抓取web流量的轻量级蜜罐 安装环境要求 apache php7.4 mysql8 github地址 https://github.com/xiaoxiaoranxxx/POT-ZHIYUN 系统演示...
面向对象程序设计之sort排序
目录 java 升序 降序 c# 升序 倒序 小结 敲过排序算法的都会的,Sort排序与compareTo的改写。 java 升序 一般自带的sort方法就是升序的。 Arrays.sort(arr);//传入要排序的数组,默认升序 Collections.sort(list);//传入要排序的集合类&am…...

ARM学习(29)NXP 双coreMCU MCXN94学习
笔者来介绍一下NXP 双core板子 ,新系列的mcxn94 1、MCX 新系列介绍 恩智浦 MCU 系列产品包括 Kinetis 、LPC 系列,以及 i.MX RT 系列,现在又推出新系列产品 MCX 产品,包括四个系列,目前已经发布产品的是 MCX N 系列。…...

视频剪辑免费素材哪里能找到?
在创作视频时,素材的选择至关重要。为了让您的项目更具吸引力和专业性,我整理了8个剪辑必备素材网站,它们提供了丰富多样的资源,从高清视频到优质音乐,应有尽有。让我们一起探索这些资源丰富、质量上乘的平台ÿ…...
多线程为什么是你必需要掌握的知识
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、多线程是什么?二、多线程学习的必要性1.提升代码性能2.更优秀的软件设计和架构3.更好的工作机会 总结 前言 相信每一位开发者,都应…...

转转上门履约服务拆分库表迁移实践
文章目录 1 背景2 数据迁移方案2.1 方案一:双写新旧库2.2 方案二:灰度开关切换新旧库 3 迁移细节3.1 业务代码改造3.2 数据同步3.3 数据一致性校验 4 总结5 参考资料 1 背景 随着业务不断发展,一个服务中部分功能模块适合沉淀下来作为通用的…...

upload-labs 1-19关 攻略 附带项目下载地址 小白也能看会
本文章提供的工具、教程、学习路线等均为原创或互联网收集,旨在提高网络安全技术水平为目的,只做技术研究,谨遵守国家相关法律法规,请勿用于违法用途,如有侵权请联系小编处理。 环境准备: 1.靶场搭建 下…...
如何设置SQL Server的端口:详细步骤指南
如何设置SQL Server的端口:详细步骤指南 在SQL Server中,配置端口是确保数据库服务能够正确通信的重要步骤。无论是为了提高安全性还是满足特定的网络配置需求,正确设置SQL Server的端口都是必要的。本文将详细介绍如何设置SQL Server的端口…...

昇思25天学习打卡营第16天|Diffusion扩散模型,DCGAN生成漫画头像
Diffusion扩散模型 关于扩散模型(Diffusion Models)有很多种理解,本文的介绍是基于denoising diffusion probabilistic model (DDPM),DDPM已经在(无)条件图像/音频/视频生成领域取得…...

【吊打面试官系列-Dubbo面试题】Dubbo SPI 和 Java SPI 区别?
大家好,我是锋哥。今天分享关于 【Dubbo SPI 和 Java SPI 区别?】面试题,希望对大家有帮助; Dubbo SPI 和 Java SPI 区别? JDK SPI JDK 标准的 SPI 会一次性加载所有的扩展实现,如果有的扩展吃实话很耗时&…...
7.31 Day13 网络散记(http,https...)
http固定对应80端口 https固定对应443端口...
LumaLabs 用例和应用分析
介绍 LumaLabs AI 是一家尖端技术公司,通过创新使用人工智能 (AI) 和神经渲染技术,彻底改变了 3D 内容创作领域。本报告深入探讨了 LumaLabs AI 的各种用例和应用,重点介绍了其在不同行业中的能力、优势和潜在影响。 LumaLabs AI 概述 LumaL…...
leetcode88.合并两个有序数组(简单题!)
思路:合并两个数组,再进行排序(利用快速排序) class Solution(object):def quicksort(self, num, i, j):if i>j: # 跳出循环的条件要出来return left iright jtemp num[i]while left < right:while left < right and…...

鸿蒙(HarmonyOS)DatePicker+TimePicker时间选择控件
一、操作环境 操作系统: Windows 11 专业版、IDE:DevEco Studio 3.1.1 Release、SDK:HarmonyOS 3.1.0(API 9) 二、效果图 可实现两种选择方式,可带时分选择,也可不带,使用更加方便。 三、代码 SelectedDateDialog…...
2024年和2025年CFA FRM CAIA ESG自己整理的资料
本人金融女一枚,CFA FRM CAIA ESG已过,研究生学历,职位投资经理。从事金融快5年了,月薪30000,周未双休五险一金。工作很充实也很累,每天失眠,思考了很久,还是决定离职了,…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法
深入浅出:JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中,随机数的生成看似简单,却隐藏着许多玄机。无论是生成密码、加密密钥,还是创建安全令牌,随机数的质量直接关系到系统的安全性。Jav…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...

SpringCloudGateway 自定义局部过滤器
场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!
简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求,并检查收到的响应。它以以下模式之一…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...