当前位置:网站首页>实验六 继承和多态
实验六 继承和多态
2022-07-06 09:22:00 【文文喜欢郭子吖】
实验六 继承和多态
实验目的
1. 掌握接口的使用方法
2. 掌握子类的继承性、子类对象的创建过程
3. 掌握成员变量的继承与隐藏、方法的继承与重写
实验学时 6学时
实验内容
1. 编写程序为公交车的老人卡、学生卡和普通市民卡提供收费功能。将充值、收费功能提取,定义在一个接口中,然后被这三种卡类实现。最后编写一个测试类,用于测试公交车三类卡的刷卡操作。
package code61;
public interface Buscard { //定义接口Bus card
void recharge();
void charge();
}
package code61;
public class Oldpeople implements Buscard { //实现接口
public void recharge() {
System.out.println("老年卡充值成功!"); //重写接口的充值方法
}
public void charge() {
System.out.println("使用老年卡,扣一元!"); //重写接口的收费方法
}
}
package code61;
public class People implements Buscard { //实现接口
public void recharge() {
System.out.println("普通市民卡充值成功!"); //重写接口充值方法
}
public void charge() {
System.out.println("使用普通市民卡,扣2元!"); //重写接口收费方法
}
}
package code61;
public class Student implements Buscard { //实现接口
public void recharge() {
System.out.println("学生卡充值成功!"); //重写接口充值方法
}
public void charge() {
System.out.println("使用学生卡,扣1.5元!"); //重写接口收费方法
}
}
package code61;
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Oldpeople O = new Oldpeople();
O.recharge();
O.charge(); //定义老年卡对象,并调用充值、收费方法
Student S = new Student();
S.recharge();
S.charge(); //定义学生卡对象,并调用充值、收费方法
People P = new People();
P.recharge();
P.charge(); //定义市民卡对象,并调用充值、收费方法
}
}
2.设计四个类、一个接口,类之间的关系如下:
在类App中使用Compute、Circle、Rectangle类,在Compute类中使用Shape接口(Shape对象作为computeArea方法的形式参数),Circle、Rectangle类实现接口Shape,重写area()方法。图中“+”的表示public,“-”的表示private,框图中上面一栏是类或接口的名称,中间一栏是属性,下面一栏是方法。
在App类的main()中:
- 创建一个Compute类对象、一个Circle类对象和一个Rectangle类对象。
- 调用Compute对象的computeArea方法(实际参数为Circle对象)计算圆的面积。
- 调用Compute对象的computeArea方法(实际参数为Rectangle对象)计算矩形面积。
package code62;
public class App {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Compute a = new Compute();
Circle b = new Circle(2);
Rectangle c = new Rectangle(2,2);
System.out.println("圆的面积为:"+a.computArea(b)); //调用Compute对象的computeArea方法,实参为Circle对象
System.out.println("矩形面积为:"+a.computArea(c)); //调用Compute对象的computeArea方法,实参为Rectangle对象
}
}
package code62;
public class Circle implements Shape { //实现接口
private int radius;
public Circle(int radius) {
this.radius=radius;
}
public double area() {
return PI*radius*radius; //重写接口的area方法,求圆的面积
}
}
package code62;
public class Compute {
public double computArea(Shape s) { //Shape对象作为该方法的形式参数
return s.area();
}
}
package code62;
public class Rectangle implements Shape { //实现接口
private int width;
private int height;
public Rectangle(int width,int height) {
this.width=width;
this.height=height;
}
public double area() {
return width*height; //重写接口的area方法,求矩形面积
}
}
package code62;
public interface Shape { //定义接口
double PI=3.14;
double area();
}
3. 普通门和报警门。
(1)定义一个接口Alarm(报警),含有一个报警方法void alarm( );
(2)定义一个类Door(普通门),Door类有一个私有属性name(品牌);有4个公有方法getName、setName、open(开门)、close(关门);open、close方法的功能由自己确定。
(3)定义一个类AlarmDoor(报警门),继承Door类,实现接口Alarm,重写接口中的抽象方法alarm(方法的功能由自己确定)。
(3)编写一个测试类DoorTest,在main方法中,给出多种型号的报警门和普通门,调用开门、关门、报警等动作。
package code63;
public interface Alarm { //定义接口
void alarm();
}
package code63;
public class AlarmDoor extends Door implements Alarm { //继承Door类,实现接口Alarm
public void alarm() {
System.out.println(this.getName()+"嘟嘟嘟!警报响起!"); //重写接口中的抽象方法
}
}
package code63;
public class Door {
private String name; //私有属性name
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public void open() {
System.out.println(this.name+"门开了!");
}
public void close() {
System.out.println(this.name+"门关了!");
}
}
package code63;
public class DoorTest {
public static void main(String[] args) {
// TODO 自动生成的方法存根
AlarmDoor a1 = new AlarmDoor();
a1.setName("低级报警门!");
a1.open();
a1.alarm(); //创建对象a1,并调用各方法
AlarmDoor a2 = new AlarmDoor();
a2.setName("高级报警门!!!");
a2.open();
a2.close();
a2.alarm(); //创建对象a2,并调用各方法
AlarmDoor a3 = new AlarmDoor();
a3.setName("普通门.");
a3.open();
a3.close(); //创建对象a3,并调用各方法
}
}
4. 设计五个类(测试类、计算机类、手机类、充电器类、U盘类)、一个接口(Usb接口),各类之间的关系如下:
(1)在UsbTest类的main方法中,创建一个Xiaomi手机对象、一个小米CDQ012M充电器对象、一台联想电脑、一个Kingston U盘对象。然后将充电器插入手机充电,将U盘插入计算机。
(2)在Mobile类的InsertUsb方法中,连接Usb。
(3)在Computer类的InsertUsb方法中,连接Usb。
(4)在Charger类的connect方法中,输出“已连接充电器,正在充电...”。
(5)在UDisk类的connect方法中,输出“已连接U盘器,正在读取数据...”。
package code64;
public class Charger implements Usb {
private String brand;
public Charger(String brand) {
this.brand=brand;
}
public void connect() {
System.out.println("已连接充电器"+this.brand+",正在充电..."); //重写接口的connect方法
}
}
package code64;
public class Computer {
private String brand;
public Computer(String brand) {
this.brand=brand;
}
public void insertUsb(Usb device) {
System.out.println(this.brand);
device.connect(); //构造连接方法
}
}
package code64;
public class Moblie {
private String brand;
public void Moblie(String brand) {
this.brand=brand;
}
public void insertUsb(Usb device) {
System.out.println(this.brand);
device.connect(); //构造连接方法
}
}
package code64;
public class UDisk implements Usb {
private String brand;
public UDisk(String brand) {
this.brand=brand;
}
public void connect() {
System.out.println("已连接U盘器"+this.brand+",正在读取数据..."); //重写接口的connect方法
}
}
package code64;
public interface Usb { //定义接口
void connect();
}
package code64;
public class UsbTest {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Moblie a = new Moblie();
a.Moblie("Xiaomi"); //创建手机对象
Charger b = new Charger("小米CDQ012M"); //创建充电器对象
Computer c = new Computer("联想"); //创建电脑对象
UDisk d = new UDisk("Kingston"); //创建U盘对象
a.insertUsb(b); //充电器插入手机
c.insertUsb(d); //U盘插入计算机
}
}
5. 设计一个武器系统,要求如下:
(1)定义一个弹药类Bullet,有一个弹药名称属性name。设计一个构造方法及set、get方法。
(2)定义一个可装载弹药的接口Loadable,该接口有一个装载的抽象方法load()。
(3)定义一个可发射弹药的接口Launchable,该接口有一个发射的抽象方法launch()。
(4)定义一个武器类Weapon,既可以装弹,也可以发射。
武器类有一个属性name(武器名称)、可使用的弹药bullet(Bullet对象)以及对应的get、set方法。
重写load方法,在方法中输出装载的弹药。
重写launch方法,在方法中输出发射的弹药。
(4)定义3个普通武器类:Tank、Flighter、WarShip都继承武器类Weapon。 每个普通武器类都有一个带一个参数name的构造方法,在构造方法中创建弹药对象。
坦克Tank使用的弹药是炮弹,战斗机Flighter使用的弹药是导弹,舰艇WarShip使用的弹药是鱼雷。
(5)定义一个类Army,代表一支军队,包括:。
1) 属性:ArrayList<Weapon> weapon用来存放军队装备的各种武器,自己查找集合类ArrayList的用法和泛型的知识点;
2) 获取军队的拥有的武器数量方法getNum;
3)添置武器的方法addWeapon
4) 让所有武器都装载弹药的方法loadAll;
5)让所有武器都发起攻击的方法luanchAll。
(6)编写一个测试类,在main方法中:
1)建立一支强大的军队;
2)添置各种型号武器,包括坦克、战机、舰艇。
3)输出军队拥有的武器数量;
4)让所有的武器都装上弹药;
5)让所有的武器都发射。
package code65;
import java.util.ArrayList;
public class Army {
ArrayList<Weapon> weapon;
public Army() {
weapon = new ArrayList<Weapon>(); //存放军队装备的各种武器
}
public int getNum() {
return weapon.size(); //获取军队的拥有的武器数量
}
public void addWeapon(Weapon weapon) {
this.weapon.add(weapon); //添置武器
}
public void loadAll() {
System.out.println("所有武器准备装弹药...");
int a=1;
for(Weapon weapon:weapon) {
System.out.print(a+":"+weapon.getName());
weapon.load();
a++; //让所有武器都装载弹药
}
}
public void luanchAll() {
System.out.println("所有武器准备战斗...");
int a=1;
for(Weapon weapon:weapon) {
System.out.print(a+":"+weapon.getName());
weapon.launch();
a++; //让所有武器都发射弹药
}
}
}
package code65;
public class Bullet {
private String name;
public Bullet(String name) { //构造方法
this.name=name;
}
public void setName(String name) {
this.name=name;
}
public String getName() {
return name;
}
}
package code65;
public class Flighter extends Weapon { //继承武器类
public Flighter(String name) {
setName(name);
Bullet bullet = new Bullet("导弹"); //创建导弹对象
setBullet(bullet);
}
}
package code65;
public interface Launchable { //定义一个可发射弹药的接口
void launch();
}
package code65;
public interface Loadable { //定义一个可装载弹药的接口
void load();
}
package code65;
public class Tank extends Weapon { //继承武器类
public Tank(String name) {
setName(name);
Bullet bullet = new Bullet("炮弹"); //创建炮弹对象
setBullet(bullet);
}
}
package code65;
public class WarShip extends Weapon { //继承武器类
public WarShip(String name) {
setName(name);
Bullet bullet = new Bullet("鱼雷"); //创建鱼雷对象
setBullet(bullet);
}
}
package code65;
public class Weapon implements Loadable,Launchable { //实现两接口
private String name;
private Bullet bullet;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public Bullet getBullet() {
return bullet;
}
public void setBullet(Bullet bullet) {
this.bullet=bullet;
}
public void load() {
System.out.println("装载"+this.bullet.getName()); //重写接口的装载方法
}
public void launch() {
System.out.println("发射"+this.bullet.getName()); //重写接口的发射方法
}
}
package code65;
public class Test {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Tank a1 = new Tank("99坦克 ");
Flighter a2 = new Flighter("歼20 ");
WarShip a3 = new WarShip("武汉舰 ");
WarShip a4 = new WarShip("芜湖舰 ");
Flighter a5 = new Flighter("歼31 ");
Flighter a6 = new Flighter("F35 "); //建立军队
Army a = new Army();
a.addWeapon(a1);
a.addWeapon(a2);
a.addWeapon(a3);
a.addWeapon(a4);
a.addWeapon(a5);
a.addWeapon(a6); //添置各种武器
System.out.println("军队装备的武器数量:"+a.getNum());
a.loadAll(); //让所有武器装上弹药
a.luanchAll(); //让所有武器都发射
}
}
6. 设计五个类,类之间的关系如下
在类App中使用Paint、Rectangle、Circle、Rabit类,在paint类中使用AsciiArt抽象类(AsciiArt对象作为setArt方法的参数),Rectangle、Circle、Rabit类继承抽象类AsciiArt,并重写draw()方法。
具体设计步骤:
- App类的main( )
1)创建一个Paint对象paint
2)显示作品列表
========作品列表=======
- 矩形
- 圆
- 小兔子
======================
请选择:
3) 根据选择,显示不同的作品
① 画矩形
a.创建一个Rectangle对象rect。
b.调用paint的setArt方法,将rect设置为paint对象要显示的作品。
c.调用对象paint的draw方法显示作品。
②画圆
a.创建一个Circle对象c。
b.调用paint的setArt方法,将c设置为paint对象要显示的作品。
c.调用对象paint的draw方法显示作品。
③画小兔子
a.创建一个Rabit对象rabit。
b.调用paint的setArt方法,将rabit设置为paint对象要显示的作品。
c.调用对象paint的draw方法显示作品。
- Paint类中的draw( )
①显示作品名、作者。
②调用成员变量art的draw方法显示作品。
- Rectangle类中的draw( )
输出width行height列个“*”。
- Circle类中的draw( )
输出用“*”组成的圆。
- Rabit类中的draw( )
输出可爱的小兔。
package code66;
import java.util.Scanner;
public class App {
public static void main(String[] args) {
// TODO 自动生成的方法存根
Scanner in=new Scanner(System.in);
System.out.println("========作品列表=======");
System.out.println("1.矩形");
System.out.println("2.圆");
System.out.println("3.小兔子");
System.out.println("======================");
System.out.println("请选择:");
int select=in.nextInt();
Paint paint = new Paint();
switch(select){ //根据选择,显示不同作品
case 1:
Rectangle rect = new Rectangle("矩形","张三",3,8);
paint.setArt(rect); //调用方法,将rect设置为paint对象要显示的作品
paint.draw(); //调用draw方法
break;
case 2:
Circle c = new Circle("圆形","小丫",4);
paint.setArt(c); //调用方法,将c设置为paint对象要显示的作品
paint.draw(); //调用draw方法
break;
case 3:
Rabit rabit = new Rabit("兔子","李四");
paint.setArt(rabit); //调用方法,将rabit设置为paint对象要显示的作品
paint.draw(); 调用draw方法
break;
}
}
}
package code66;
public abstract class AssciiArt { //定义一个抽象类
private String title; //作品名
private String author; //作者名
public AssciiArt(String title,String author) {
this.title=title;
this.author=author;
}
abstract void draw(); //抽象画图方法
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title=title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author=author;
}
}
package code66;
public class Circle extends AssciiArt { //继承AssciiArt类
private int radius;
public Circle(String title,String author,int radius) {
super(title,author); //访问父类中被覆盖的成员
this.radius=radius;
}
public void draw() { //重写画图方法
int d=2*radius;
for(int y=0;y<=d;y++) {
for(int x=0;x<=d;x++) {
if((x-radius)*(x-radius)+(y-radius)*(y-radius)<=radius*radius)
System.out.print("**");
else
System.out.print(" ");
}
System.out.println(); //输出用"*"组成的圆
}
}
}
package code66;
public class Paint {
private AssciiArt art;
public void setArt(AssciiArt art) { //AsciiArt对象作为setArt方法的参数
this.art=art;
}
public void draw() {
System.out.println("作品:"+this.art.getTitle());
System.out.println("作者:"+this.art.getAuthor());
this.art.draw(); //调用art的draw方法显示作品
}
}
package code66;
public class Rabit extends AssciiArt { //继承AssciiArt类
public Rabit(String title,String author) {
super(title,author); //访问父类中被覆盖的成员
}
public void draw() { //重写画图方法
System.out.println("/)/)");
System.out.println("(- -) )o");
System.out.println(" || ||"); //画出小兔子
}
}
package code66;
public class Rectangle extends AssciiArt { //继承AssciiArt类
private int width;
private int height;
public Rectangle(String title,String author,int width,int height) {
super(title,author); //访问父类中被覆盖的成员
this.width=width;
this.height=height;
}
public void draw() { //重写画图方法
for(int a=0;a<width;a++) {
for(int b=0;b<height;b++) {
System.out.print("*"); //输出width行height列个"*"组成的矩形
}
System.out.println();
}
}
}
实验小结
- 类的继承是实现代码复用最有效的方法;
- Java只支持单继承,即只能有一个父类,但类之间的继承可以传递;
- 继承格式:class 子类名 extends 父类名;
- 关键字super可以用来在子类中访问父类中被覆盖的成员;
- 关键字abstract修饰的类为抽象类,其更多是作为其他类的父类,其中的抽象方法必须在子类中具体实现;
- 接口定义格式:【修饰符】interface接口名;
- 接口中的所有方法都是抽象的,必须在实现该接口的子类中重写所有的抽象方法;
- 接口实现格式:class 类名 implements 接口名;
- 被实现的接口可以有多个,之间有逗号隔开;
- 另外还要去掌握ArrayList的使用方法。
边栏推荐
猜你喜欢
8. C language - bit operator and displacement operator
Mortal immortal cultivation pointer-2
MATLAB打开.m文件乱码解决办法
这次,彻底搞清楚MySQL索引
QT meta object qmetaobject indexofslot and other functions to obtain class methods attention
View UI plus released version 1.3.0, adding space and $imagepreview components
仿牛客技术博客项目常见问题及解答(二)
Caching mechanism of leveldb
[hand tearing code] single case mode and producer / consumer mode
3. Number guessing game
随机推荐
记一次猫舍由外到内的渗透撞库操作提取-flag
7. Relationship between array, pointer and array
Relationship between hashcode() and equals()
Why use redis
Inaki Ading
[the Nine Yang Manual] 2019 Fudan University Applied Statistics real problem + analysis
Read only error handling
Detailed explanation of redis' distributed lock principle
It's never too late to start. The tramp transformation programmer has an annual salary of more than 700000 yuan
1.初识C语言(1)
[modern Chinese history] Chapter V test
Caching mechanism of leveldb
Beautified table style
Aurora system model of learning database
hashCode()与equals()之间的关系
[中国近代史] 第九章测验
[面试时]——我如何讲清楚TCP实现可靠传输的机制
C语言入门指南
C language Getting Started Guide
7-11 机工士姆斯塔迪奥(PTA程序设计)