Java任务:商品库存的盘点

来自CloudWiki
跳转至: 导航搜索

任务描述

我们在前面的实训中,扩大了面馆的经营范围,已经不再只经营面条了,还经营黄焖鸡米饭等产品,

在我们的仓库类Store中,怎样编写一套代码、来适配所有商品的利润计算呢 ?

Java多态思想的简单运用。

前情回顾

我们在项目Java任务:经营范围拓展中建立了这么几个类:

Java2020-5-16.png

完成此实训,需要先把这几个类建起来。

方法重写:每类商品都不相同

现在我们假设需要计算商品的利润,需要添加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