第11天 面向对象
第1章 接口
1.1 接口概念
1.1.1 接口概念
接口是功能的集合,同样可看做是一种数据类型,是比抽象类更为抽象的”类”。
接口只描述所应该具备的方法,并没有具体实现,具体的实现由接口的实现类(相当于接口的子类)来完成。这样将功能的定义与实现分离,优化了程序设计。
请记住:一切事物均有功能即一切事物均有接口。
继承是方便类的定义,可以定义一个共性的父类 然后设置子类在继承,提高代码复用性
接口是方便了方法的使用 比如企鹅是鸟 但他不会飞 如果我们设置鸟类都会飞的方法就不合适,所以这时我们定义一个飞的接口那么到时那个鸟调用这个接口那个鸟就会飞了,接口是方便了方法的实现,提高代码的耦合性,使代码扩展性提高。
1.1.2 接口的代码体现
在代码体现中,接口的更为抽象表现为其内的所有方法均为抽象方法,同时不定义普通的成员变量(可以定义静态常量,在后边介绍)。
如同抽象类,接口在使用时同样不能创建对象。
类与接口的关系为实现关系,即类实现接口。实现的动作类似继承,只是关键字不同,实现使用implements。
其他类(实现类)实现接口后,就相当于声明:”我应该具备这个接口中的功能”。实现类仍然需要重写方法以实现具体的功能。
1.2 接口定义及使用格式
1.2.1 接口定义
a) 定义关键字
与定义类的class不同,接口定义时需要使用interface关键字。
定义接口所在的仍为.java文件,虽然声明时使用的为interface关键字的编译后仍然会产生.class文件。这点可以让我们将接口看做是一种只包含了功能声明的特殊类。
b) 定义格式
使用interface代替了原来的class,其他步骤与定义类相同:
-
方法均为公共访问的抽象方法
-
无法定义普通的成员变量
public interface 接口名 {
抽象方法1;
抽象方法2;
抽象方法3;
}
如:
public interface Careable {
public abstract void carCare();
}
}
1.2.2 接口使用
a) 类实现接口
我们使用实现来表示一个类与一个接口之间的关系,这是最常用的使用方法。
实现的关键字为implements。
格式:
Class 类 implements 接口 {
重写接口中方法
}
在实现后,该类就会将接口中的抽象方法继承过来,此时该类需要重写该抽象方法,完成具体的逻辑。
则:
-
接口中定义功能,一切类需要具有该功能时均可以实现该接口,只声明了应该具备该方法,是功能的声明。
-
具体实现类中重写方法,实现功能,是方法的具体实现。
于是,通过以上两个动作将功能的声明与实现便分开了。(此时请重新思考:类是现实事物的描述,接口是功能的集合。)
/*
* 哺乳动物
*
* 姓名
* 年龄
*
* 吃 睡
*/
public abstract class BRDW {
private String name;
private int age;
public abstract void eat();
public abstract void sleep();
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 class BianFu extends BRDW implements Fly{
@Override
public void eat() {
System.out.println("蝙蝠吃蛾子");
}
@Override
public void sleep() {
System.out.println("蝙蝠倒挂着睡");
}
@Override
public void open() {
System.out.println("打开小翅膀");
}
@Override
public void fly(double height) {
System.out.println("蝙蝠能飞"+height+"米高");
}
@Override
public void close() {
System.out.println("关闭小翅膀");
}
}
/*
* 飞的接口
*
* 展开翅膀
*
* 飞
*
* 着陆(关闭翅膀)
*
* 方法均为公共访问的抽象方法
*/
public interface Fly {
//展开翅膀
public abstract void open();
//飞
public abstract void fly(double height);
//关闭翅膀
public abstract void close();
}
/*
* 哺乳动物
* 老虎 蝙蝠
*/
public class Test {
public static void main(String[] args) {
BianFu bf = new BianFu();
bf.eat();
bf.sleep();
bf.open();
bf.fly(250.0);
bf.close();
}
}
//老虎没有实现接口所以老虎就没有飞的功能
/*
* 哺乳动物
* 老虎 蝙蝠
*/
public class Test {
public static void main(String[] args) {
BianFu bf = new BianFu();
bf.eat();
bf.sleep();
bf.open();
bf.fly(250.0);
bf.close();
}
}
b) 接口继承接口
如同类继承类后便拥有了父类的成员,可以使用父类的非私有成员。A接口继承B接口后,A接口便拥有了A、B两个接口中所有的抽象方法。并集关系。
c) 定义接口变量使用多态
接口经常参与多态。在后边多态时,我们详细讲解。
这里我们需要清楚,接口也是一种特殊的数据类型,就可以定义变量、作为参数声明、作为返回值声明、作为成员变量声明。
package cn.javahelp.test;
/*
* Animal的类
* 属性
* name
* age
* 行为
* 吃
* 睡
*/
public abstract class Animal {
//成员变量
private String name;
private int age;
//吃
public void eat(){
System.out.println("动物吃");
}
//睡
public void sleep(){
System.out.println("睡");
}
//-----------get/set-------------------
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;
}
}
package cn.javahelp.test;
/*
* 定义看门接口
*/
public interface LookDoor {
public abstract void lookDoor();
}
package cn.javahelp.test;
/*
* 自定义类型 家
*
* 地址
*
* 行为
* 在家吃饭
*/
public class Home {
private String address;
//动物在家吃饭
//在所有使用父类类型的地方均可以传入其子类对象。
public void eatAtHome(Animal a){
//调用Animal的eat方法
a.eat();
}
//看家方法
public void lookHome(LookDoor lk){
//调用狗看门的方法
lk.lookDoor();
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
package cn.javahelp.test;
/*
*定义一个狗类
* 属性
* name
* age
* kind
* 行为
* 吃
* 睡
* 看门
*/
public class Dog extends Animal implements LookDoor{
private String kind;
@Override
public void eat(){
System.out.println("狗吃肉");
}
//狗特有功能 看门
@Override
public void lookDoor(){
System.out.println("狗看门");
}
public String getKind() {
return kind;
}
public void setKind(String kind) {
this.kind = kind;
}
}
package cn.javahelp.test;
public class Pig extends Animal implements LookDoor{
@Override
public void lookDoor() {
System.out.println("猪看门");
}
@Override
public void eat() {
System.out.println("猪吃");
}
}
package cn.javahelp.test;
/**
* 测试家类
*
* 任何使用父类或父接口的地方都可以传入其子类(实现类对象)对象
*/
public class Test {
public static void main(String[] args) {
//创建Home对象
Home home = new Home();
Dog d = new Dog();
//lookHome需要的是一个看门的接口 我传入的实际参数是一个实现类的对象
home.lookHome(d);
Pig p = new Pig();
home.lookHome(p);
//--------------------------------
System.out.println("-----------------------");
Cat cat = new Cat();
Animal a = new Cat();
home.eatAtHome(cat);
}
public static Animal get(){
Animal a = new Dog();
return a;
}
}
1.3 接口注意事项
-
Java支持一个类同时实现多个接口。
一个类可以有多个接口书写加上逗号即可implements List<E>,RandomAccess,Cloneable
-
Java支持一个接口同时继承多个接口。这里取并集。C继承A和B同时拥有AB的方法。
-
类可以在继承一个类的同时,实现多个接口。
子类继承父类与接口中的方法,当父类和接口的方法相同时,子类只需要实现一次即可。
-
接口与父类的功能可以重复,均代表要具备某种功能,并不冲突。
-
接口中的成员是有固定修饰符abstract的,如果没有写,也会自动加入:(接口中都是常量没有变量)
新建一个接口
public abstract interface Fu{
public void fly();
}
我们把abstract去掉在fly方法中加入方法体看下报错说明,证明接口自动加入了修饰符abstract,因为抽象类是没有方法体的。写上方法体eclipse自动报错修正。
“变量”修饰符为:public static final(static与final面向对象第5天讲解)
方法修饰符为:public abstract(所以依据方法重写的访问权限注意事项,重写接口方法时,必须使用public)
public abstract interface Fu{
public void fly();
}
public class Zi implements Fu{
@Override
Public void fly(){
}
}
这里我们把父类的public去掉 也把子类的public去掉那么会看到子类会报错,eclipse提示要 添加public。这里建议大家永远加上public abstract。
-
当一个类实现了接口时,必须实现其所有的方法,否则这个类会保留一些抽象方法,此时,该类包含了抽象方法,便必须定义为一个抽象类。
比如:接口中有三个方法,你实现了两个方法,那么还包含了一个抽象方法,那这个类也必须是一个抽象类。
-
接口里面可以没有任何方法。
虽然接口是功能的集合,没有方法没有意义,此时这个接口的作用就是一个标记,像宋江被脸上打上标记一样,就是让你知道。
1.4 接口的思想
前面学习了接口的代码体现,现在来学习接口的思想,接下里从生活中的例子进行说明。
举例:我们都知道电脑上留有很多个插口,而这些插口可以插入相应的设备,这些设备为什么能插在上面呢?主要原因是这些设备在生产的时候符合了这个插口的使用规则,否则将无法插入接口中,更无法使用。发现这个插口的出现让我们使用更多的设备。
总结:接口在开发中的它好处
1、接口的出现扩展了功能。
2、接口其实就是暴漏出来的规则。
3、接口的出现降低了耦合性,即设备与设备之间实现了解耦。
接口的出现方便后期使用和维护,一方是在使用接口(如电脑),一方在实现接口(插在插口上的设备)。例如:笔记本使用这个规则(接口),电脑外围设备实现这个规则(接口)。
1.5 接口和抽象类的区别
明白了接口思想和接口的用法后,接口和抽象类的区别是什么呢?接口在生活体现也基本掌握,那在程序中接口是如何体现的呢?
通过实例进行分析和代码演示抽象类和接口的用法。
1、举例:
-
犬:
-
行为:
-
吼叫;
-
吃饭;
-
-
-
缉毒犬:
-
行为:
-
吼叫;
-
吃饭;
-
缉毒;
-
-
2、思考:
由于犬分为很多种类,他们吼叫和吃饭的方式不一样,在描述的时候不能具体化,也就是吼叫和吃饭的行为不能明确。当描述行为时,行为的具体动作不能明确,这时,可以将这个行为写为抽象行为,那么这个类也就是抽象类。
可是当缉毒犬有其他额外功能时,而这个功能并不在这个事物的体系中。这时可以让缉毒犬具备犬科自身特点的同时也有其他额外功能,可以将这个额外功能定义接口中。
如下代码演示:
interface 缉毒{
public abstract void 缉毒();
}
//定义犬科的这个提醒的共性功能
abstract class 犬科{
public abstract void 吃饭();
public abstract void 吼叫();
}
// 缉毒犬属于犬科一种,让其继承犬科,获取的犬科的特性,
//由于缉毒犬具有缉毒功能,那么它只要实现缉毒接口即可,这样即保证缉毒犬具备犬科的特性,也拥有了缉毒的功能
class 缉毒犬 extends 犬科 implements 缉毒{
public void 缉毒() {
}
void 吃饭() {
}
void 吼叫() {
}
}
class 缉毒猪 implements 缉毒{
public void 缉毒() {
}
}
1.5.1 接口和抽象类的相同点
-
都位于继承的顶端,用于被其他类实现或继承;
-
都不能直接实例化对象;
-
都包含抽象方法,其子类都必须覆写这些抽象方法;
1.5.2 接口和抽象类的区别:
-
抽象类为部分方法提供实现,避免子类重复实现这些方法,提高代码重用性;接口只能包含抽象方法;
-
一个类只能继承一个直接父类(可能是抽象类),却可以实现多个接口;(接口弥补了Java的单继承)
1.5.3 接口和抽象类的选用:
-
优先选用接口,尽量少用抽象类;
需要定义子类的行为,又要为子类提供共性功能时才选用抽象类;
1.5.4 接口和抽象类的使用区别总结
-
类继承类extends,只能单继承
接口继承接口extends可以多继承
类实现接口implements可以多实现
接口不可以继承类!
-
抽象类中可以有非抽象方法
接口中全部为抽象方法
-
抽象类具有成员变量
接口没有普通的成员变量
-
抽象类中的成员无固定修饰符
接口中的成员有固定修饰符
第2章 多态
2.1 多态概述
多态是继封装、继承之后面向对象的第三大特性。
现实事物经常会体现出多种形态,如学生,学生是人的一种,则一个具体的同学张三既是学生也是人,即出现两种形态。
Java作为面向对象的语言,同样可以描述一个事物的多种形态。如Student类继承了Person类,一个Student的对象便既是Student,又是Person。
2.2 多态概念
Java中多态的代码体现在一个子类对象(实现类对象)既可以给这个子类(实现类对象)引用变量赋值,又可以给这个子类(实现类对象)的父类(接口)变量赋值。
如Student类可以为Person类的子类。那么一个Student对象既可以赋值给一个Student类型的引用,也可以赋值给一个Person类型的引用。
最终多态体现为父类引用变量可以指向子类对象。
多态的前提是必须有子父类关系或者类实现接口关系,否则无法完成多态。
在使用多态后的父类引用变量调用方法时,会调用子类重写后的方法。
Animal a = new Cat(); 猫是一个动物
多态优点:
配合继承与方法重写提高了代码的复用性与扩展性,如果没有方法重写,则多态同样没有意义。
2.3 多态的定义与使用格式
父类引用指向子类对象就是多态的定义格式。同一个父类的方法会被不同的子类重写为各自的具体实现。在调用方法时,调用的为各个子类重写后的方法。调用父类的功能运行的是子类重写后的功能
父类类型 变量名 = new 子类类型();
变量名.方法名();
此时,虽然该变量指向的是子类对象,但表现为一个父类的形态,可以调用一切父类的方法,子类特有的方法将不能调用。
2.4 多态的使用场景
我们一般在以下场景当中使用多态:
-
成员变量赋值、局部变量赋值
-
方法传参
-
返回值返回值
2.5 多态的存在意义
当变量名指向不同的子类对象时,由于每个子类重写父类方法的内容不同,所以会调用不同的方法。
如:
在Boss类中,有叫员工去工作的方法,当该方法的参数定义为接口时,可以传入任意的子类对象。相比定义多个子类参数,定义多个方法,这样大大提高了代码复用性与扩展性。
class Boss{
public void goToWork(Empolyee e){
e.work();
}
}
所以多态的存在意义(优点)为:
配合继承与方法重写提高了代码的复用性与扩展性,如果没有方法重写,则多态同样没有意义。
2.6 instanceof关键字
我们可以通过instanceof关键字来判断某个对象是否属于某种数据类型。如学生的对象属于学生类,学生的对象也属于人类。
使用格式:
boolean b = 对象 instanceof 数据类型
2.7 向上转型与向下转型
多态本身是子类类型向父类类型向上转型的过程。
多态的转型分为向上转型与向下转型两种:
-
向上转型:当有子类对象赋值给一个父类引用时,便是向上转型,多态本身就是向上转型的过程。
使用格式:
父类类型 变量名 = new 子类类型();
如:Person p = new Student();
-
向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用转为子类引用,这个过程是向下转型。如果是直接创建父类对象,是无法向下转型的!
使用格式:
子类类型 变量名 = (子类类型) 父类类型的变量;
如:Student stu = (Student) p; //变量p 实际上指向Student对象
2.8 多态细节规则
-
编译时,检查父类引用变量的数据类型是否包含对应的成员方法与成员变量。
-
运行时,成员方法调用子类重写方法,没有用private修饰的成员变量访问时,访问的为父类类型的。
-
或简单记忆:只有在调用方法时,调用的时子类重写方法,其他一切表现均为父类类型。
public class Fu {
String name = "父类名字" ;
public void method(){
System.out.println("父类方法");
}
}
public class Zi extends Fu{
String name = "子类名字";
int age ;
@Override
public void method(){
System.out.println("子类方法");
}
public void method2(){
System.out.println("子类特有方法");
}
}
/*
* 向上转型
* 多态 父类引用指向子类对象 这本身就是向上转型
* 当调用方法时,调用的是父类的方法 但是在运行时运行的是子类重写后的方法
* 不能调用子类特有的方法
* 例如:
* 向上转型:有人请你父亲去讲课,父亲不在,你穿上你父亲的衣服去讲课,你讲的内容肯定是你自己的;
* 向下转型:你自己有打游戏的方法但是你要脱下衣服变回儿子才能去打游戏。
*
* 打印成员变量时,打印的是父类的
*
* 向下转型
* 当本身是子类对象,向上转型为父类类型后,可以通过强制类型转换,转换回子类对象
*
*多态时
* 编译时
* 成员方法 看等号左边
* 成员变量 看等号左边
* 运行时
* 成员方法 看等号右边
* 成员变量 看等号左边
*
*/
public class Test {
public static void main(String[] args) {
Fu fu = new Fu();
fu.method();
Zi zi = new Zi();
zi.method();
zi.method2();
System.out.println("----------------------");
//多态本身就是向上转型
Fu fz = new Zi();
//向上转型后,一切表现形式都是父类的表现形式,不能调用子类特有的功能
fz.method();
//类型强转回顾
//double b = 12.0;
//int a = (int)b;
//向下转型 使用强制类型转换进行转换
Zi zf = (Zi)fz;
//向下转向那个后可以调用子类特有方法
zf.method();
zf.method2();
System.out.println("================");
System.out.println(fz.name);
System.out.println("=============");
//本身就是父类对象不可以转换成子类
//Zi z = (Zi)fu;
}
}
第3章 综合案例---家养宠物案例
3.1 案例介绍与演示
题目要求1(多态):
定义家类
方法:饲养动物
动物类:
属性:年龄、姓名
方法:吃饭、睡觉
猫类、狗类、猪类均为动物类的一种。
创建家类对象,调用家的饲养动物方法。
题目要求2(接口与多态):
定义看门的功能接口:
方法:看门
家类中添加新的功能:安排宠物看家方法
假设:猪和狗具备看家的功能
创建家类对象,调用安排宠物看家的方法
3.2 案例分析
题目要求1(多态):
家类饲养动物方法定义时为父类,即动物类,则在调用饲养动物时,可以传入任意的子类对象,猫、狗、猪均可。
/*
* 动物类
* 属性:年龄、姓
* 方法:吃饭、睡觉
*/
public abstract class Animal {
private String name;
private int age;
public abstract void eat();
public abstract void sleep();
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 class Cat extends Animal{
@Override
public void eat() {
System.out.println("猫吃鱼");
}
@Override
public void sleep() {
System.out.println("猫躺着睡");
}
public void catchMouse(){
System.out.println("猫抓老鼠");
}
}
public class Dog extends Animal {
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("趴着睡");
}
}
public class Pig extends Animal implements LookDoor{
@Override
public void eat() {
System.out.println("猪什么都吃");
}
@Override
public void sleep() {
System.out.println("猪吃完了就睡");
}
}
/*
* 饲养动物方法
*/
public class Home {
//饲养动物的方法
public void feedAnimal(Animal a){
a.eat();
}
}
/*
* 测试 家类 饲养动物方法
*/
public class Test {
public static void main(String[] args) {
Home home = new Home();
Animal a = new Dog();
Cat c = new Cat();
home.feedAnimal(a);
}
}
题目要求2(接口与多态):
家类看家的方法定义时无法为动物类,因为并不是所有的类均有看门的方法,这里设计为狗与猪类具有看门的方法,则二者可以实现看门接口,获取看门方法,重写看门方法。在定义看门的方法时,定义接收看门接口的类型。则在实际调用方法时,只要是实现了该接口的类的对象均可以传入。
/*
* 动物类
* 属性:年龄、姓
* 方法:吃饭、睡觉
*/
public abstract class Animal {
private String name;
private int age;
public abstract void eat();
public abstract void sleep();
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 interface LookDoor {
public abstract void lookDoor();
}
public class Dog extends Animal implements LookDoor{
@Override
public void eat() {
System.out.println("狗吃肉");
}
@Override
public void sleep() {
System.out.println("趴着睡");
}
@Override
public void lookDoor() {
System.out.println("狗汪汪的看门,逮谁咬谁!");
}
}
public class Pig extends Animal implements LookDoor{
@Override
public void eat() {
System.out.println("猪什么都吃");
}
@Override
public void sleep() {
System.out.println("猪吃完了就睡");
}
@Override
public void lookDoor() {
System.out.println("猪哼哼的看门,专拱白菜");
}
}
/*
* 饲养动物方法
*/
public class Home {
//饲养动物的方法
public void feedAnimal(Animal a){
a.eat();
}
//安排宠物看家的方法
public void lookHome(LookDoor lk){
lk.lookDoor();
}
}
/*
* 测试 家类 饲养动物方法
*/
public class Test {
public static void main(String[] args) {
Home home = new Home();
Animal a = new Dog();
Cat c = new Cat();
home.feedAnimal(a);
//多态
LookDoor lk = new Dog();
LookDoor lk2 = new Pig();
home.lookHome(lk2);
}
}
第4章 笔记本电脑案例
4.1 案例介绍
定义USB接口(具备开启功能、关闭功能),笔记本要使用USB设备,即笔记本在生产时需要预留可以插入USB设备的USB接口,即就是笔记本具备使用USB设备的功能,但具体是什么USB设备,笔记本并不关心,只要符合USB规格的设备都可以。鼠标和键盘要想能在电脑上使用,那么鼠标和键盘也必须遵守USB规范,不然鼠标和键盘的生产出来无法使用
进行描述笔记本类,实现笔记本使用USB鼠标、USB键盘
-
USB接口,包含开启功能、关闭功能
-
笔记本类,包含运行功能、关机功能、使用USB设备功能
-
鼠标类,要符合USB接口
-
键盘类,要符合USB接口
4.2 案例需求分析
阶段一:
使用笔记本,笔记本有运行功能,需要笔记本对象来运行这个功能
阶段二:
想使用一个鼠标,又有一个功能使用鼠标,并多了一个鼠标对象。
阶段三:
还想使用一个键盘 ,又要多一个功能和一个对象
问题:每多一个功能就需要在笔记本对象中定义一个方法,不爽,程序扩展性极差。
降低鼠标、键盘等外围设备和笔记本电脑的耦合性。
4.3 实现代码步骤
-
定义鼠标、键盘,笔记本三者之间应该遵守的规则
interface USB {
void open();// 开启功能
void close();// 关闭功能
}
l 鼠标实现USB规则
class Mouse implements USB {
public void open() {
System.out.println("鼠标开启");
}
public void close() {
System.out.println("鼠标关闭");
}
}
-
键盘实现USB规则
class KeyBoard implements USB {
public void open() {
System.out.println("键盘开启");
}
public void close() {
System.out.println("键盘关闭");
}
}
-
定义笔记本
class NoteBook {
// 笔记本开启运行功能
public void run() {
System.out.println("笔记本运行");
}
// 笔记本使用usb设备,这时当笔记本对象调用这个功能时,必须给其传递一个符合USB规则的USB设备
public void useUSB(USB usb) {
// 判断是否有USB设备
if (usb != null) {
usb.open();
usb.close();
}
}
public void shutDown() {
System.out.println("笔记本关闭");
}
}
public class Test {
public static void main(String[] args) {
// 创建笔记本实体对象
NoteBook nb = new NoteBook();
// 笔记本开启
nb.run();
// 创建鼠标实体对象
Mouse m = new Mouse();
// 笔记本使用鼠标
nb.useUSB(m);
// 创建键盘实体对象
KeyBoard kb = new KeyBoard();
// 笔记本使用键盘
nb.useUSB(kb);
// 笔记本关闭
nb.shutDown();
}
}
第5章 本日自习作业:
5.1 知识点相关题
5.1.1 什么是接口?如何定义接口?
5.1.2 接口与抽象类有哪些不同?
5.1.3 多态是什么?或者多态的代码体现是什么?
5.1.4 如何使用多态(至少说出2种多态的具体使用方式代码),一定要使用多态么?多态有什么好处? 试举一例,说明多态的好处。
5.1.5 产生多态后,使用变量时,是父类的表现还是子类的表现?验证语法错误看子类还是父类,调用方法时,调用子类方法还是父类方法?
5.1.6 instanceof关键字有什么作用
5.1.7 尝试使用接口/抽象类作为成员变量类型,并赋值(了解)
如:家类有”家庭宠物”的成员变量,家庭宠物为Animal类型,而Animal可以继续有子类。则在给家类的家庭宠物变量赋值时,可以给予子类对象赋值。
5.1.8 以下对接口描述错误的有()
A) 接口没有提供构造方法
B) 接口中的方法默认使用public、abstract修饰
C) 接口中的属性默认使用public、static、final修饰
D) 接口不允许多继承
答案:D
5.1.9 有关接口的描述不正确的是
A接口是一种引用类型
B接口支持多继承
C接口中的方法都没有方法体
D一个接口可以继承其他接口的变量
答案:D
5.1.10 以下哪个接口的定义是正确的?
A.interface B{void print() { } }
B.abstract interface B { void print() }
C.abstract interface B extends A1,A2 { abstract void print(){ };
D.interface B { void print();}
答案:D
5.1.11 Java中能实现多重继承功能的方式是?
A.接口
B.同步
C.抽象类
D.父类
答案:A
5.1.12 下列叙述正确的是?
A.Java中允许多重继承
B.Java一个类只能实现一个接口
C.Java中只能单重继承
D.Java中一个类可以继承多个抽象类
答案:C
5.1.13 以下程序运行的结果是:
public class EE { public static void main(String[] args) { A a = new B(); a.show();
B b = new C(); b.show(); } }
class A { public void show() { show2(); }
public void show2() { System.out.println("我"); } }
class B extends A { public void show2() { System.out.println("爱"); } }
class C extends B { public void show() { super.show(); } public void show2() { System.out.println("你"); } } |
答案: 爱 你
5.1.14 有篮球运动员和乒乓球运动员 有篮球教练和乒乓球教练 为了出国比赛 乒乓球相关的人需要学习英语
package cn.javahelp7.test;
/*
* 定义Person
* name age
* 睡吃
*/
public abstract class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
//吃
public abstract void eat();
//睡
public abstract void sleep();
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;
}
}
package cn.javahelp7.test;
/*
*运动员类
*/
public abstract class Player extends Person{
//运动员特有方法 运动
public abstract void play();
public Player() {
super();
}
public Player(String name, int age) {
super(name, age);
}
}
package cn.javahelp7.test;
/*
* 教练类
*/
public abstract class Teacher extends Person{
//教练特有方法 教
public abstract void teacher();
public Teacher() {
super();
}
public Teacher(String name, int age) {
super(name, age);
}
}
package cn.javahelp7.test;
/*
* 兵乓球运动员
*/
public class PPQPlayer extends Player implements IStudyEnglish{
public PPQPlayer() {
super();
}
public PPQPlayer(String name, int age) {
super(name, age);
}
@Override
public void play() {
System.out.println("乒乓球运动员玩乒乓球");
}
@Override
public void eat() {
System.out.println("乒乓球运动员吃乒乓球运动员套餐");
}
@Override
public void sleep() {
System.out.println("乒乓球运动员睡乒乓球运动员公寓");
}
@Override
public void studyEnglish() {
System.out.println("乒乓球运动员学习乒乓球英语");
}
}
package cn.javahelp7.test;
/*
* 乒乓球教练类
*/
public class PPQTeacher extends Teacher implements IStudyEnglish{
public PPQTeacher() {
super();
}
public PPQTeacher(String name, int age) {
super(name, age);
}
@Override
public void teacher() {
System.out.println("乒乓球教练教乒乓球运动员");
}
@Override
public void eat() {
System.out.println("乒乓球教练吃乒乓球教练套餐");
}
@Override
public void sleep() {
System.out.println("乒乓球教练睡乒乓球教练公寓");
}
@Override
public void studyEnglish() {
System.out.println("乒乓球教练学习乒乓球英语");
}
}
package cn.javahelp7.test;
public class LQPlayer extends Player {
public LQPlayer() {
super();
}
public LQPlayer(String name, int age) {
super(name, age);
}
@Override
public void play() {
System.out.println("篮球运动员玩篮球");
}
@Override
public void eat() {
System.out.println("篮球运动员吃篮球运动员套餐");
}
@Override
public void sleep() {
System.out.println("篮球运动员睡篮球运动员公寓");
}
}
package cn.javahelp7.test;
/*
* 篮球教练类
*/
public class LQTeacher extends Teacher{
public LQTeacher() {
super();
}
public LQTeacher(String name, int age) {
super(name, age);
}
@Override
public void teacher() {
System.out.println("篮球教练教篮球运动员");
}
@Override
public void eat() {
System.out.println("篮球教练吃篮球教练套餐");
}
@Override
public void sleep() {
System.out.println("篮球教练睡篮球教练公寓");
}
}
package cn.javahelp7.test;
/*
* 学英语接口
*/
public interface IStudyEnglish {
public abstract void studyEnglish();
}
package cn.javahelp7.test;
public class Test {
public static void main(String[] args) {
//乒乓球运动员对象
PPQPlayer ppqp = new PPQPlayer("刘备",40);
ppqp.eat();
ppqp.sleep();
ppqp.play();
ppqp.studyEnglish();
System.out.println("------------------------");
PPQTeacher ppqt = new PPQTeacher("诸葛亮" ,20);
ppqt.eat();
ppqt.sleep();
ppqt.teacher();
ppqt.studyEnglish();
System.out.println("------------------------");
LQPlayer lqp = new LQPlayer("赵云",18);
lqp.eat();
lqp.sleep();
lqp.play();
System.out.println(lqp.getName());
System.out.println("------------------------");
LQTeacher lqt = new LQTeacher("吕布",30);
lqt.eat();
lqt.sleep();
lqt.teacher();
lqt.getName();
System.out.println(lqt.getName());
System.out.println(lqt.getAge());
System.out.println(lqt.getClass());
}
}
5.2 代码题:
5.2.1 多态成员的特点习题
要求:
1.定义明星类,有姓名和年龄的属性,且属性不写private修饰符,提供无返回值的无参数的自我介绍的方法,方法内容为:”我是明星xxx,我今年xxx岁了;”
2.定义明星的子类,重写父类的自我介绍的方法,内容为:”我是明星子类,我的名字是xxx,我今年xxx岁了;”,提供一个无参数的无返回值的跳舞的方法,内容为:”我是明星的子类,我跳拉丁舞......”
3.定义测试类,使用多态的形式创建明星的子类的对象,使用该对象分别给姓名和年龄属性赋值,再调用自我介绍的方法,然后通过类型转换,调用子类跳舞的方法;
答案:
/* * 明星类: * 属性: * 姓名 * 年龄 * 方法: * 自我介绍 */ public class MingXing { //属性 String name; int age; //自我介绍的方法 public void ziWoJieShao(){ System.out.println("我是明星"+name+",我今年"+age+"岁了;"); } } /* * 明星子类: * 方法: * 自我介绍 * 跳舞 */ public class MingXingZi extends MingXing { //重写父类的自我介绍的方法 public void ziWoJieShao(){ System.out.println("我是明星子类,我的名字是"+super.name+",我今年"+super.age+"岁了;"); } //跳舞的方法 public void tiaoWu(){ System.out.println("我是明星的子类,我跳拉丁舞......"); } } /* * 测试类 */ public class Test { public static void main(String[] args) { //1、使用多态的形式创建明星的子类的对象 MingXing mx = new MingXingZi(); //2、赋值 mx.name = "德华"; mx.age = 40; //3、调用自我介绍的方法 mx.ziWoJieShao(); //4、向下转型 MingXingZi mxz = (MingXingZi)mx; //5、调用跳舞的方法 mxz.tiaoWu(); } } |
5.2.2 参数多态的使用习题
要求:
1.定义动物类,动物类有抽象的无返回值的无参数的“嚎叫”方法;
2.定义猫类,继承动物类,猫叫的声音为:“小猫喵喵叫...”,提供无返回值的无参数的抓老鼠的方法,内容为:”小猫抓老鼠...”;
3.定义狗类,继承动物类,狗叫的声音为:“小狗汪汪叫...”;
4.定义人类,提供无返回值的带1个动物类型参数的逗动物玩的方法,在方法内部让动物嚎叫,且如果该动物是小猫,就让小猫抓老鼠;
5.定义测试类,分别创建猫的对象,狗的对象,人的对象,用人的对象调用逗动物玩的方法,分别测试小猫对象和小狗对象;
答案:
/* * 抽象的动物类: * 方法: * 抽象的嚎叫方法 */ public abstract class DongWu { public abstract void haoJiao(); } /* * 猫类继承动物类: * 方法: * 嚎叫 * 抓老鼠 */ public class Mao extends DongWu{ //嚎叫的方法 public void haoJiao() { System.out.println("小猫喵喵叫..."); } //抓老鼠的方法; public void zhuaLaoShu() { System.out.println("小猫抓老鼠..."); } } /* * 狗类继承动物类 */ public class Gou extends DongWu{ //嚎叫的方法 public void haoJiao() { System.out.println("小狗汪汪叫..."); } } /* * 人类: * 方法: * 逗动物玩 */ public class Ren { //逗动物玩 public void douDongWuWan(DongWu d){ //1、让动物嚎叫 d.haoJiao(); //2、判断该动物是不是小猫 if(d instanceof Mao){ //3、是猫就强转成猫类型,调用抓老鼠的方法 Mao m = (Mao)d; m.zhuaLaoShu(); } } } /* * 测试类 */ public class Test { public static void main(String[] args) { //1、分别创建猫的对象,狗的对象,人的对象 Mao m = new Mao(); Gou g = new Gou(); Ren r = new Ren(); //2、用人的对象调用逗动物玩的方法,分别测试小猫对象和小狗对象 r.douDongWuWan(g); r.douDongWuWan(m); } } |
5.2.3 接口多态的使用习题
要求:
1.定义主持人接口,提供一个无参数无返回值的主持的方法;
2.定义学生类,提供一个无参数的无返回值的抽象的吃方法;
3.定义男同学类,继承学生类,吃的方法内容为:”我是男同学,我嗑瓜子,喝啤酒...”;
4.定义女同学类,继承学生类,同时实现主持人接口,主持方法的内容为:”女士们,先生们,大家好,我是主持人......”,吃的方法内容为:”我是女同学,我嗑瓜子,吃水果...”;
5.定义班级类,提供一个无返回值的,带两个参数的开晚会的方法,其中第1个参数为主持人接口类型,第二个参数为学生类型,方法内容中要求先调用主持人的主持方法,再打印一句话”晚会正式开始.....”,然后调用学生的吃的方法;
6.定义测试类,使用多态的形式分别创建学生类型的对象,主持人类型的对象,班级类型的对象(这个对象非多态),使用班级对象调用开晚会的方法;
答案:
/* * 主持人接口: * 方法: * 主持 */ public interface ZhuChiRen { public abstract void zhuChi(); } /* * 学生类: * 方法: */ public abstract class XueSheng { public abstract void chi(); } /* * 男同学类,继承学生类 */ public class NanTongXue extends XueSheng{ public void chi(){ System.out.println("我是男同学,我嗑瓜子,喝啤酒..."); } } /* * 女同学类,继承学生类,同时实现主持人接口 */ public class NvTongXue extends XueSheng implements ZhuChiRen{ //重写学生类中的抽象的吃的方法 public void chi(){ System.out.println("我是女同学,我嗑瓜子,吃水果..."); } //实现主持人接口的主持的方法 public void zhuChi() { System.out.println("女士们,先生们,大家好,我是主持人......"); } } /* * 班级类 * 方法: * 开班会 */ public class BanJi { //无返回值的,带两个参数的开晚会的方法,其中第1个参数为主持人接口类型,第二个参数为学生类型 public void kaiBanHui(ZhuChiRen z,XueSheng x){ //1、先调用主持人的主持方法 z.zhuChi(); //2、打印一句话”晚会正式开始.....” System.out.println("晚会正式开始....."); //3、然后调用学生的吃的方法 x.chi(); } } /* * 测试类 */ public class Test { public static void main(String[] args) { //1、使用多态的形式分别创建学生类型的对象,主持人类型的对象, XueSheng x = new NanTongXue(); ZhuChiRen z = new NvTongXue(); //2、创建班级类型的对象(这个对象非多态), BanJi b = new BanJi(); //3、使用班级对象调用开晚会的方法 b.kaiBanHui(z, x); } } |