Java任务:商品库存的盘点
目录
任务描述
我们在前面的实训中,扩大了面馆的经营范围,已经不再只经营面条了,还经营黄焖鸡米饭等产品,
在我们的仓库类Store中,怎样编写一套代码、来适配所有商品的利润计算呢 ?
Java多态思想的简单运用。
前情回顾
我们在项目Java任务:经营范围拓展中建立了这么几个类:
完成此实训,需要先把这几个类建起来。
方法重写:每类商品都不相同
现在我们假设需要计算商品的利润,需要添加getProfit方法 来计算利润。
这个计算利润的方法每个商品类别都需要,因此我们一开始在父类Goods中添加。
父类Goods
在父类Goods中添加getProfit方法:
public float getProfit() { float p =this.price *0.15f; return p; }
子类Noodles
但是后来发现,面条类的利润率偏高,因此父类中通用的计算利润的方法不能用了,
因此我们可以在子类Noodles中重写getProfit方法:
public float getProfit() { float p =this.price *0.5f; return p; }
子类Rice类
再后来发现,假设米饭类商品是新上单品,老板赔钱促销,利润率为0,
因此子类Rice类中的getProfit也需要重新写一下
public float getProfit() { return 0; }
运用多态:一套函数计算所有商品
上述利润计算函数只能计算单件商品的利润。
如果计算仓库中所有商品的利润,就得到仓库类Store中去解决问题了。
计算单件商品利润并不难,难的是每种商品的利润计算方法都不一样。这只能通过多态去解决。
修改数组类型为Goods
原先面馆仓库类Store类中的商品类型都为Noodles,由于现在经营范围扩大后,新增的米饭等商品无法用这一类来表示。因此,我们需要首先拓展的是仓库中商品的类型(修改数组类型)。
我们将面馆仓库类中的货物类型统一由Noodles类改为Goods,同时在数组中增添其他类的商品
Store类中:
package entity; public class Store { private Goods [] gset; private int num ; public Store() { num = 3; gset = new Goods[num]; gset[0]= new Goods("山西刀削面",105.0f,30); gset[1]= new Noodles("兰州牛肉面",15.0f,20); gset[2]= new Rice("黄焖鸡米饭",12.0f,30,false); }
编写利润计算方法totalProfit
然后,在Store类中编写totalProfit方法,对库存商品的利润进行汇总。
总利润 = 单个商品利润 * 单个商品数量
单个商品利润调用刚才编写的getProfit方法进行计算,然后把它们相加即为总利润。
public float totalProfit() { float total=0; for(Goods g:this.gset) { total += g.getNum()*g.getProfit(); } return total; }
注意,这里虽然每件商品的利润计算方法都叫getProfit,
但是由于刚才我们对这些getProfit方法进行了重写,因此它们的利润计算方法各不相同,
在这个totalProfit方法中,对单件商品利润的计算都是调用的getProfit(),保持了各个子类形式上的相同,保持了上层代码的稳定,同时又在每个类内部对getProfit方法的具体实现进行了重写,体现了多态思想的运用,实现了一套函数代码处理多个类的效果。
现在,我们在Store类的main方法中进行调用:
Store s = new Store(); 。。。 System.out.println("今天面馆的毛利为:"); System.out.println(s.totalProfit()+" 元");
完整代码
Goods类
package entity; public class Goods { protected String name;//名称 protected float price;//价格 protected int num;//数量 public Goods() { } public Goods(String n,float p,int num) { this.name = n; this.price = p; this.num = num; } public String getName() {//name的读方法 return this.name; } public void setName(String newName) {//name的写方法 this.name = newName; } public float getPrice( ){//价格的读方法 return this.price; } public void setPrice(float p) {//价格的写方法 if(p<=0) { System.out.println("价格必须为正!"); }else { this.price =p; } } public int getNum() {//num的读方法 return this.num; } public void setNum(int num) { if(num<0) { System.out.println("数量不能为负!"); }else { this.num=num; } } public String toString() { String s=""; s= "名称:"+this.name+"; 价格:"+this.price +"; 数量:"+this.num+";"; return s; } public float getProfit() { float p =this.price *0.15f; return p; } public static void main(String[] args) { // TODO Auto-generated method stub Goods g1= new Goods("黄焖鸡米饭",15,1); System.out.println("每件商品毛利为:"+g1.getProfit()); } }
Noodles类
package entity; public class Noodles extends Goods{ String flavor; //空构造方法 public Noodles(){ } public Noodles(String n,float p,int num) { super(n,p,num);//调用父类的构造方法 this.flavor ="不辣"; } public Noodles(String n,float p,int num,String f) { super(n,p,num);//调用父类的构造方法 this.flavor= f; } public String getFlavor() { return this.flavor; } public void setFlavor(String f) { this.flavor =f; } public String toString() {//重写父类的方法 String str ="名称:"+this.name+ " 价格:"+this.price+ " 数量:"+ this.num + " 口味:"+this.flavor; return str; } public float getProfit() { float p =this.price *0.5f; return p; } public static void main(String[] args) { System.out.println("第一份商品:"); Noodles n1= new Noodles();//声明一个Noodle类的对象n1 n1.setName("炸酱面"); //调用父类方法 n1.setPrice(10);//调用父类方法 n1.setNum(2);//调用父类方法 n1.setFlavor("不辣");//调用本类方法 System.out.println(n1.toString());//调用重写了的父类方法 System.out.println(); System.out.println("第二份商品:"); Noodles n2= new Noodles("刀削面",15.0f,3,"微辣"); System.out.println(n2.toString());////调用重写了的父类方法 System.out.println("每件商品毛利为:"+n2.getProfit()); } }
Rice类
package entity; public class Rice extends Goods{ private boolean isBig;//是大份还是小份 public void showWeight() { if(isBig==true) { System.out.println("该份是小份米饭"); } } public Rice(){ super("黄焖鸡米饭",15,1); this.isBig=false; } public Rice(String n,float p,int num,boolean isBig) { super(n,p,num); this.isBig=isBig; } public String toString() { String s=""; s= "名称:"+this.name+"; 价格:"+this.price +"; 数量:"+this.num+";大/小份:"+this.isBig; return s; } public float getProfit() { return 0; } public static void main(String[] args) { // TODO Auto-generated method stub Rice r2= new Rice("黄焖鸡米饭",20.0f,3,true); System.out.print("餐品的名称为:"); System.out.println(r2.name);//调用父类成员变量 System.out.print("餐品的数量为:"); System.out.println(r2.getNum());//调用父类成员方法 System.out.print("餐品是否为大份:"); System.out.println(r2.isBig);//调用本类成员方法 r2.showWeight();//调用本类成员方法 System.out.println(r2.toString());//调用toString方法 } }
Store类:
package entity; public class Store { private Goods [] gset; private int num ; public Store() { num = 3; gset = new Goods[num]; gset[0]= new Goods("山西刀削面",105.0f,30); gset[1]= new Noodles("兰州牛肉面",15.0f,20); gset[2]= new Rice("黄焖鸡米饭",12.0f,30,false); } public int getNum() { return this.num; } public void getSet() { for(int i=0;i<gset.length;i++) { System.out.println(gset[i].toString()); } } public String showInfo() { String total=""; for(int i=0;i<gset.length;i++) { total +=gset[i].toString()+"\n"; } return total; } public String showInfo(String name) { String s="暂无商品信息"; for(int i=0;i<this.gset.length;i++){ if (this.gset[i].getName().equals(name)) { s = this.gset[i].toString(); //虽然每个子类的商品都调用了toString方法 //但是它们的具体内容却不一样,体现了多态 } } return s; } public float totalProfit() { float total=0; for(Goods g:this.gset) { total += g.getNum()*g.getProfit(); } return total; } @Override public String toString() { String total=""; for(int i=0;i<gset.length;i++) { total +=gset[i].toString()+"\n"; } return total; } public static void main(String[] args) { // TODO Auto-generated method stub Store s = new Store(); System.out.println("仓库的商品总数为:"+s.getNum()); System.out.println("以下为商品详情信息:"); System.out.println(s.showInfo()); System.out.println("查找黄焖鸡米饭:"); System.out.println(s.showInfo("黄焖鸡米饭")); System.out.println("今天面馆的毛利为:"); System.out.println(s.totalProfit()+" 元"); } }
多态的其他体现
在本例中,Goodds类、Noodles类、Rice类它们的toString()方法各不相同,在Store类中通过遍历,把它们的toString方法一一调用了出来,这是不是也是多态在本例中的又一应用呢 ?
Goods类:
public String toString() { String s=""; s= "名称:"+this.name+"; 价格:"+this.price +"; 数量:"+this.num+";"; return s; }
Noodles类:
public String toString() {//重写父类的方法 String str ="名称:"+this.name+ " 价格:"+this.price+ " 数量:"+ this.num + " 口味:"+this.flavor; return str; }
Rice类:
public String toString() { String s=""; s= "名称:"+this.name+"; 价格:"+this.price +"; 数量:"+this.num+";大/小份:"+this.isBig; return s; }
Store类中的showInfO方法():
public String showInfo() { String total=""; for(int i=0;i<gset.length;i++) { total +=gset[i].toString()+"\n"; } return total; }
可以看到调用Store类中的showInfO方法())方法,不同的商品打印的toString方法是不一样的,也集中体现了多态思想
名称:山西刀削面; 价格:105.0; 数量:30; 名称:兰州牛肉面 价格:15.0 数量:20 口味:不辣 名称:黄焖鸡米饭; 价格:12.0; 数量:30;大/小份:false