接口和内部类编程练习
一、动物声音“模拟器”
设计一个动物声音“模拟器”,希望模拟器可以模拟许多动物的叫声,要求如下:
(1)编写接口Animal
Animal接口有2个抽象方法cry()和getAnimalName(),即要求实现该接口的各种具体的动物给出自己的叫声和种类名称。
(2)编写模拟器类Simulator
该类有一个playSound(Animal animal)方法,该方法的参数是Animal类型。即参数animal可以调用实现Animal接口类重写的cry()方法播放具体动物的声音,调用重写的getAnimalName()方法显示动物种类的名称。
(3)编写实现Animal接口的类:Dog和Cat类
各类的UML图如下所示:
在各类中通过构造方法实现对成员变量的初始化。
编写主类Application(用户程序)
在主类Application的main方法中至少包含如下代码。
Simulator simulator = new Simulator();
simulator.playSound(new Dog(“藏獒”));
simulator.playSound(new Cat(“加菲猫”));
接口Animal:
package package4_1;
public interface Animal {
public abstract void cry();
public abstract String getAnimalName();
}
模拟器类Simulator:
package package4_1;
public class Simulator {
void playSound(Animal animal){
System.out.println( animal.getAnimalName() + " may cry like this: ");
animal.cry();
}
}
Dog类:
package package4_1;
public class Dog implements Animal {
String name;
Dog(String name){
this.name=name;
}
public void cry(){
System.out.println("汪汪汪~");
}
public String getAnimalName(){
return name;
}
}
Cat类:
package package4_1;
public class Cat implements Animal{
String name;
Cat(String name){
this.name=name;
}
public void cry(){
System.out.println("喵喵喵~");
}
public String getAnimalName(){
return name;
}
}
Text测试主类:
package package4_1;
public class Text {
public static void main(String[] args) {
Simulator simulator = new Simulator();
simulator.playSound(new Dog("藏獒"));
simulator.playSound(new Cat("加菲猫"));
}
}
运行结果:
二、评价成绩
体操比赛计算选手成绩的办法是去掉一个最高分和最低分后再计算平均分,而学校考察一个班级的某科目的考试情况时,是计算全班同学的平均成绩。Gymnastics类和School类都实现了接口ComputerAverage接口,但实现的算法不同。编写Java程序实现以上功能。
ComputerAverage接口:
public interface ComputerAverage {
public abstract double calculateAverage(double data[]);
}
Gymnastics类(调用ComputerAverage接口):
public class Gymnastics implements ComputerAverage {
public double calculateAverage(double data[]){
int cnt=data.length;
double aver=0,temp=0;
//用简单选择排序的方法,先给一组成绩数据从小到大排序。
for(int i=0;i<cnt;i++){
for(int j=i;j<cnt;j++){
if(data[j]<data[i]){
temp=data[j];
data[j]=data[i];
data[i]=temp;
}
}
}
//把除了最底分和最高分之外的成绩数据加和。(这样遍历就遍历不到最低分和最高分了)
for(int i=1;i<cnt-1;i++){
aver=aver+data[i];
}
//求去掉两个数据之后的平均分
if(cnt>2){
aver=aver/(cnt-2);
}
else
aver=0;
return aver;
}
}
School类(调用ComputerAverage接口):
public class School implements ComputerAverage {
public double calculateAverage(double data[]){
int cnt=data.length;
double aver=0;
for(int i=0;i<cnt;i++){
aver=aver+data[i];
}
aver=aver/cnt;
return aver;
}
}
Text测试主类:
public class Text {
public static void main(String[] args){
//给出两组成绩数据。其中体操成绩按照体操平均分算法计算;数学成绩按照学校平均分算法计算。
double GymnasticScore[]={95,98,90,96,100};
double MathSore[]={70,80,60,90,100};
/*
对象的上转型。
将Gymnastics类对象的引用赋给ComputerAverage接口声明的变量computer1中。
则该接口变量computer1就可以调用被Gymnastics类实现的calculateAverage方法。
*/
ComputerAverage computer1=new Gymnastics();
System.out.println("体操成绩平均分:"+computer1.calculateAverage(GymnasticScore));
ComputerAverage computer2=new School();
System.out.println("数学成绩平均分:"+computer2.calculateAverage(MathSore));
}
}
运行结果:
三、货车的装载量
货车要装载一批货物,货物由三种商品组成:电视、计算机和洗衣机。卡车需要计算出整批货物的重量。
要求有一个ComputeWeight接口,该接口中有一个方法:public double computeWeight()
有三个实现该接口的类:TV、Computer和WashMachine。这三个类通过覆盖computeWeight()方法给出自重。有一个Truck类,该类用ComputeWeight接口类型的数组作为数据成员,包含一个能计算货物总重量的方法。
编写测试类输出Truck对象所装载的货物的总重量。
ComputeWeight接口:
public interface ComputeWeight {
public double computeWeight();
}
Computer类(调用ComputeWeight接口):
public class Computer implements ComputeWeight {
public double computeWeight(){
return 3;
}
}
TV类(调用ComputeWeight接口):
public class TV implements ComputeWeight {
public double computeWeight(){
return 4;
}
}
WashMachine类(调用ComputeWeight接口):
public class WashMachine implements ComputeWeight {
public double computeWeight(){
return 5;
}
}
Truck类:
public class Truck {
ComputeWeight[] goods; //用ComputeWeight接口类型的数组作为数据成员
double totalweights=0;
//构造方法
Truck(ComputeWeight[] goods){
this.goods=goods;
}
//
public void setgoods(ComputeWeight[] goods){
this.goods=goods;
}
//计算货物总重量。
//每一件货物都有一个自重,所有货物的自重加起来就是这批货物(goods数组)的总重(totalweights)。
public double getTotalweights(){
for(int i=0;i<goods.length;i++){
totalweights=totalweights+goods[i].computeWeight();
}
return totalweights;
}
}
Text测试主类:
public class Text {
public static void main(String[] args) {
// TODO Auto-generated method stub
ComputeWeight[] goods=new ComputeWeight[10];
//简单把货物分为3类。
for(int i=0;i<goods.length;i++){
if(i%3==0){//此时货物为电视
goods[i]=new TV();
}
if(i%3==1){//此时货物为电脑
goods[i]=new Computer();
}
if(i%3==2){//此时货物为洗衣机
goods[i]=new WashMachine();
}
}
//货车truck1,装着goods这组货物。
Truck truck1=new Truck(goods);
System.out.println("货车装载的货物总重量:"+truck1.getTotalweights());
/*
对于数组goods中的每一个good[i],都已分配给不同的类的对象(电视/电脑/洗衣机),
则调用truck1.getTotalweights(),具体执行也是对应类重写的getTotalweights()方法。
*/
}
}
运行结果:
四、内部购物券
手机专卖店为了促销自己的产品,决定发行内部购物券,但其他商场不能发行该购物券。编写一个MobileShop类(模拟手机专卖店),该类中有一个名字为InnerPurchaseMoney的内部类(模拟内部购物券)。
请按模板要求,将代码替换为Java程序代码。
MobileShop类(包含内部类InnerPurchaseMoney):
public class MobileShop {
//代码1:用内部类InnerPurchaseMoney声明对象purchaseMoney1
InnerPurchaseMoney purchaseMoney1;
//代码2:用内部类InnerPurchaseMoney声明对象purchaseMoney2
InnerPurchaseMoney purchaseMoney2;
private int mobileAmount; //手机数量
MobileShop(){
//代码3:创建价值为20000的purchaseMoney1
purchaseMoney1=new InnerPurchaseMoney(20000);
//代码4:创建价值为10000的purchaseMoney2
purchaseMoney2=new InnerPurchaseMoney(10000);
}
void setMobileAmount(int m){
mobileAmount=m;
}
int getMobileAmount(){
return mobileAmount;
}
//内部类InnerPurchaseMoney
class InnerPurchaseMoney{
int moneyValue;
//内部类构造方法
InnerPurchaseMoney(int m){
moneyValue=m;
}
void buyMobile(){
if(moneyValue>=20000){
mobileAmount=mobileAmount-6;
System.out.printf("用价值%d的内部购物券买了6部手机\n", moneyValue);
}
else if(moneyValue<20000&&moneyValue>=10000){
mobileAmount=mobileAmount-3;
System.out. printf("用价值%d的内部购物券买了3部手机\n", moneyValue);
}
}
}
}
Text测试主类:
public class Text {
public static void main(String args[]){
MobileShop shop=new MobileShop();
shop.setMobileAmount(30);
System.out.printf("手机专卖店目前有%d部手机\n", shop.getMobileAmount());
shop.purchaseMoney1.buyMobile();
shop.purchaseMoney2.buyMobile();
System.out.printf("手机专卖店目前有%d部手机\n", shop.getMobileAmount());
}
}
运行结果:
五、检查危险品
车站检查危险品的设备,如果发现危险品会发出警告。编程模拟设备发现危险品。
编写一个Exception的子类DangerException,该子类可以创建异常对象,该异常对象调用toShow()方法输出“属于危险品”。
编写一个Machine类,该类的方法checkBag(Goods goods)当发现参数goods是危险品时(goods的isDanger属性是true)将抛出DangerException异常。
程序在主类的main()方法中的try-catch语句的try部分让Machine类的实例调用checkBag(Good goods)方法,如果发现危险品就在try-catch语句的catch部分处理危险品。