新人小白,初识Java,独立完成了第二季最后的作业,其中的一些经验想与大家分享,望后至之士,酌情采纳。
刚开始我看到那个项目作业的时候,脑袋里也是一片空白,Java入门第二季面向对象的知识学的也是糊里糊涂,我觉得初学编程最难的地方就是从学习到自己动手写的过程,也就是编程思想的形成,而我恰好处于这个地方。我不想再次放弃,想想自己对面向对象还是很模糊,就从封装那里重新看,看完了自己动手写,写的是老师在抽象类那章留下的例题:计算长方形和圆形的面积、周长。开始只用了封装的get/set方法,运行成功后,又重新看了继承那章的内容,并加入了继承的方法改写了原来的程序,也运行成功了,然后又看了多态。这一过程花了两三天的时间,我对面向对象的思想的理解比原来更深刻了。然后我又花了一天的时间,写出了答答租车系统,完成了作业。每一次的编程都是一次自我思考的过程,同时在编程的过程中也在积累着经验,至此我才体会到前辈们说的学习编程勤打代码是最重要的!
今天是国庆节,重新写了答答租车系统。在看了慕课网的java入门视频后,脑子里还是很混乱的,对于面向对象的内容还不是十分理解,到了第三季的异常和集合框架,看的更是一脸懵逼,但是我真的很想学好java,所以我又去网上找了别的入门是重新开始看。我看的是毕向东老师的25天入门视频,内容深入浅出,也十分的幽默,看起来也不会太累。在看完了十天的内容后,也就是讲完了面向对象的封装、继承和多态,我觉得再将这个答答租车系统写一遍。
刚开始我仅仅想到租车的序号、汽车名称、租金抽象成一个父类,建立载人车、载货车和皮卡雪三个子类,因为容量有载人和载货之分,载人车不具备载货功能,载货车又不具备载人功能,所以我并没有把容量这个属性放到父类中去。这里,我是参考了慕友的思路,将载人和载货这两个功能抽象成两个接口,由载人车实现载人接口,传入容量属性;由载货车实现载货接口,传入容量属性;而皮卡雪需要同时实现这两个接口。感觉真的是十分巧妙而有趣。
在写代码的过程中,我从慕友的代码中学习的了:通过创建父类类型对象数组来批量的进行对象初始化,当然这个方法我并没有在其他地方见过,以后还会在实践中来探索它的使用方法。同时我也学到了toString()方法的使用:当打印一个对象时,如果该对象所属的类中包含了toString()方法,那么就会自动调用toString()方法打印其中的内容,toString()方法时Object类中给定的方法,使用时通常都要进行改写。我也遇到了一个问题:就是当要利用多态进行向下转型来使用子类独有的方法时,不能讲父类类型对象数组向下转型为子类类型对象数组,会报错,而只能将对象一个一个转型,不知是否是这样的?在这次的重写的代码中,我也新增实现了输出所租汽车名称的去重,也就是如果同一辆车被重复选择,再输的账单上,该汽车名称只会出现一次,具体实现方法可以看我代码中的注释。
下面是我的答答租车系统的代码
//父类 Car
public class Car {
private int id;
private String name;
private int price;
public Car() {}
public void setId(int id)
{
this.id=id;
}
public int getId()
{
return this.id;
}
public void setName(String name)
{
this.name=name;
}
public String getName()
{
return this.name;
}
public void setPrice(int price)
{
this.price=price;
}
public int getPrice()
{
return this.price;
}
public String toString()
{
return this.id+"\t"+this.name+"\t"+this.price+"\t";
}
}
//接口类 载人功能
public interface People {
public void setPeople(int people);
public int getPeople();
}
//接口类 载货功能
public interface Goods {
public void setGoods(int goods);
public int getGoods();
}
//子类 载人车
public class PeopleCar extends Car implements People {
private int people;
public PeopleCar(int id,String name,int price,int people)
{
super.setId(id);
super.setName(name);
super.setPrice(price);
this.setPeople(people);
}
@Override
public void setPeople(int people)
{
this.people=people;
}
public int getPeople() {
// TODO Auto-generated method stub
return people;
}
public String toString()
{
return super.getId()+"\t"+super.getName()+"\t"+super.getPrice()+"元/天"+"\t"+"载人:"+getPeople();
}
}
//子类 载货车
public class GoodsCar extends Car implements Goods {
private int goods;
public GoodsCar(int id,String name,int price,int goods)
{
super.setId(id);
super.setName(name);
super.setPrice(price);
this.setGoods(goods);
}
public void setGoods(int goods)
{
this.goods=goods;
}
@Override
public int getGoods() {
// TODO Auto-generated method stub
return goods;
}
public String toString()
{
return super.getId()+"\t"+super.getName()+"\t"+super.getPrice()+"元/天"+"\t"+"载货:"+this.getGoods();
}
}
//子类 皮卡雪
public class PickCar extends Car implements Goods, People {
private int people;
private int goods;
public PickCar(int id,String name,int price,int people,int goods)
{
super.setId(id);
super.setName(name);
super.setPrice(price);
this.setPeople(people);
this.setGoods(goods);
}
public void setPeople(int people)
{
this.people=people;
}
@Override
public int getPeople() {
// TODO Auto-generated method stub
return people;
}
public void setGoods(int goods)
{
this.goods=goods;
}
@Override
public int getGoods() {
// TODO Auto-generated method stub
return goods;
}
public String toString()
{
return super.getId()+"\t"+super.getName()+"\t"+super.getPrice()+"元/天"+"\t"
+"载人:"+this.getPeople()+"载货:"+this.getGoods();
}
}
//实现类
import java.util.Scanner;;
public class MainTest {
private static Scanner input=new Scanner(System.in);
private static Car[] car= {new PeopleCar(1, "奥迪A4", 500,4),//多态,父类引用指向子类对象
new PeopleCar(2, "马自达6", 400, 4),//在创建对象的时候直接对对象进行初始化
new PickCar(3, "皮卡雪6", 450, 4, 2),//因为在子类中定义了含参的构造方法
new PeopleCar(4, "金龙", 800, 20),
new GoodsCar(5, "松花江", 400, 4),
new GoodsCar(6, "依维河", 1000, 20)};
private static void print(String str)//自定义的输出字符串的方法
{
System.out.println(str);
}
private static int carNums()//输入你要租车的数量
{
print("请输入您要租车的数量:");
return inPut(2);
}
private static int[] carSelect(int num)//接收输入的租车数量,循环打印提示要租车的序号,
{ //并把序号存入一个数组中
int[] ids=new int[num];
for(int i=1;i<=num;i++)
{
print("******请输入第"+i+"辆车的序号******");
int in=input.nextInt();
while(in<1||in>6)//输入选择车辆的序号超出给定范围不予通过
{
print();
print("******请输入第"+i+"辆车的序号******");
in=input.nextInt();
}
ids[i-1]=in;//将输入的要租车的序号存储到数组ids中
}
return ids;
}
private static void print()//重写自定义函数print
{
print("******请输入合法的数据******");
}
private static int inPut(int i)//判断输入的值是否异常
{
int in=input.nextInt();
if(i==1)
{
while(in!=0&&in!=1)
{
print();
print("您是否要租车:1:是 0:否");
in=input.nextInt();
}
}else if(i==2)
{
while(in<1)
{
print();
print("请输入您要租车的数量:");
in=input.nextInt();
}
}else if(i==3)
{
while(in<1)
{
print();
print("******请输入租车天数******");
in=input.nextInt();
}
}
return in;
}
private static int days()
{
print("******请输入租车天数******");
return inPut(3);
}
//下面是我设计的输出汽车名称去重算法,感觉有点麻烦
/*既然载人车和载货车要分别计算和输出,不如将得到的选择的车辆数组ids分成载人和载货两个数组
定义两个函数peopleIds和goodsIds,传入ids数组参数,返回只载人和只载货的数组
*/
private static int[] peopleIds(int[] ids)
{
int[] peopleIds= new int[ids.length];
for(int i=0;i<ids.length;i++)
{
if(ids[i]!=5&&ids[i]!=6)
peopleIds[i]=ids[i];
else
continue;
}
return peopleIds;
}
private static int[] goodsIds(int[] ids)
{
int[] goodsIds=new int[ids.length];
for(int i=0;i<ids.length;i++)
{
if(ids[i]==3||ids[i]==5||ids[i]==6)
goodsIds[i]=ids[i];
else
continue;
}
return goodsIds;
}
/*然后定义两个去重函数,接收分别接收载人车和载货车的序号数组,先进行选择比较:取第一个元素,和其他元素比较,
* 如果两个元素“==”了,就将该元素置为0,依次循环
* 然后要通过get方法取得车辆的名字,其中要判断一下如果数组的元素值为0,就continue,最后打印一下
* */
private static String[] peopleCarNames(int[] arr)
{
int[] peopleIds=arr;
for(int i=0;i<peopleIds.length-1;i++)
{
for(int j=i+1;j<peopleIds.length;j++)
{
if(peopleIds[i]==peopleIds[j])
peopleIds[i]=0;
else
continue;
}
}
String[] peopleCarNames=new String[arr.length];
for(int k=0;k<peopleCarNames.length;k++)
{
if(peopleIds[k]==0)
continue;
else
peopleCarNames[k]=car[peopleIds[k]-1].getName();
}
return peopleCarNames;
}
private static String[] goodsCarNames(int[] arr)
{
int[] goodsIds=arr;
for(int i=0;i<goodsIds.length-1;i++)
{
for(int j=i+1;j<goodsIds.length;j++)
{
if(goodsIds[i]==goodsIds[j])
goodsIds[i]=0;
else
continue;
}
}
String[] goodsCarNames=new String[arr.length];
for(int k=0;k<goodsCarNames.length;k++)
{
if(goodsIds[k]==0)
continue;
else
goodsCarNames[k]=car[goodsIds[k]-1].getName();
}
return goodsCarNames;
}
//因为不给已经创建好固定长度的字符串所有元素赋值,所以出现了null,所以要手动打印数组,并且去除null
private static void printArrays(String[] arr)
{
for(int i=0;i<arr.length;i++)
{
if(arr[i]==(null))
continue;
else
System.out.print(arr[i]+"\t");
}
}
/*因为需要调用子类独有的获取载人数或载货数的方法,所以需要利用多态进行向下转型,但是需要注意的是因为之前创建的类型为Car的数组中
* 包含了三个子类的对象,所以如果直接强制向下转型为某一个子类对象数组,将出现子类A属于子类B的错误,所以需要处理一下,
* 我的做法是,将每个子类中每一个对象分别向下进行转型,再调用子类的方法。(我之前尝试将Car类型数组划分为三个与之对应的子类型数组,
* 再将此数组进行向下转型,依然报错,难度是对象所属之间也有冲突?不太明白,求高人解答)
* */
//需要计算载货车和载人车的荷载数,计算值可以直接打印输出,只需要传入之前分离好的载人车或载货车序号数组,
//通过get方法获取数值,再进行计算就可以了,需要注意的是,传入的数组参数中可能会存在值为0的元素,需要判断一下
private static void peopleSum(int[] arr) {
PeopleCar people1=(PeopleCar)car[0];
PeopleCar people2=(PeopleCar)car[1];
PeopleCar people4=(PeopleCar)car[3];
PickCar pick=(PickCar)car[2];
int sum=0;
for(int i=0;i<arr.length;i++)
{
switch(arr[i]) {
case 0: break;
case 1: sum=sum+people1.getPeople();
break;
case 2: sum=sum+people2.getPeople();
break;
case 3: sum=sum+pick.getPeople();
break;
case 4: sum=sum+people4.getPeople();
}
}
print("共载人:"+sum+"人");
}
private static void goodsSum(int[] arr)
{
PickCar pick=(PickCar)car[2];
GoodsCar goods5=(GoodsCar)car[4];
GoodsCar goods6=(GoodsCar)car[5];
int sum=0;
for(int i=0;i<arr.length;i++)
{
switch(arr[i]) {
case 0:break;
case 3:sum=sum+pick.getGoods();
break;
case 5:sum=sum+goods5.getGoods();
break;
case 6:sum=sum+goods6.getGoods();
}
}
print("共载货:"+sum+"吨");
}
/*最后计算租车的总价格,这里直接传入ids数组,调用get方法取得价格数值进行计算即可
* */
private static void sumAll(int[] ids,int days)
{
int sum=0;
for(int i=0;i<ids.length;i++)
sum=sum+car[ids[i]-1].getPrice();
print("******租车的总价格为:"+sum*days+"元");
}
//***********************************************************************
public static void main(String[] args)
{
print("--------------欢迎使用答答租车系统--------------");
print("您是否要租车:1:是 0:否");
int in=inPut(1);
if(in==1)
{
print("序号"+"\t"+"汽车名称"+"\t"+"租金"+"\t"+"容量");
for(int i=0;i<car.length;i++)
System.out.println(car[i]);//直接打印对象会自动调用Object类中的toString()方法
int num=carNums();
int[] ids=carSelect(num);
int days=days();//接收租车的天数
print("您的账单:");
print("******可载人的车有:");
printArrays(peopleCarNames(peopleIds(ids)));/*先调用分类载人车和载货车数组函数,返回载人车序号数组;
再调用将序号转换为车名函数,返回车名数组,最后调用剔除null值打印车名函数*/
peopleSum(peopleIds(ids));
print("******可载货的车有:");
printArrays(goodsCarNames(goodsIds(ids)));
goodsSum(goodsIds(ids));
sumAll(ids,days);
}else
{
print("-------------------感谢您的使用!再见!-------------------");
}
}
}