刚结束了本学期的面向对象课程,感觉学习这门课程有一定难度。对于先学C语言而言,面对java基础语法学习,反而感觉很难,其实其中最大的问题不是语法难,而是一种编程思想的转变。面向过程就是把你的代码封装成函数,然后依次去做一件事情,面向过程是把你要做的事情抽象成对象,告诉对象去做。所以要想学好java入门,必须知道类和对象的概念。
对于最后三次的大作业而言,难度提升较大,刚开始的时候没有完整的思路,无法有效的提取其中的关键信息,涉及继承,多态,封装等难度较大的编程方法,题量相对来说并不多,但是一次作业的难度顶三次,不能一次将完整的代码和思路呈现出来,需要多次断断续续的思考。
7-1的作业:考虑一款适合于小学生的卡片(Card)排序游戏,其规则为随机发放一些卡片给学生,卡片分为 四种形状:圆形(Circle)、矩形(Rectangle)、三角形(Triangle)及梯形(Trapezoid),并给出各种 卡片的相应参数,要求学生能够迅速求出各卡片的面积大小然后将卡片按照其面积值从大到小进行排 序,同时求出所有卡片的面积之和。
首先要看懂类图
很明显需要用到继承的方法,所以要建立一个父类:
abstract class Shape {
private String shapeName;
public String getShapeName() {
return shapeName;
}
public void setShapeName(String shapeName) {
this.shapeName = shapeName;
}
public Shape() {
super();
}
public Shape(String shapeName) {
super();
this.shapeName = shapeName;
}
public double getArea() {
return 0.0;
}
public boolean validate() {
return true;
}
}
重点是Comparable 接口的应用:
interface Compare {
public int compareTo(Card card);
}
class Card implements Compare {
Shape shape;
public Shape getShape() {
return shape;
}
public void setShape(Shape shape) {
this.shape = shape;
}
public Card(Shape shape) {
super();
this.shape = shape;
}
public Card() {
super();
}
@Override
public int compareTo(Card card) {
return 0;
}
}
将这两步较为完善的写出来就相对容易很多,根据父类写出子类,然后完成主函数,完善细节即可。
7-2的题目是在前一题的升级处理,需要在上次的代码上加一些方法即可,首先范围发生了变化。
if(list.size() == 0) {
System.out.println("Wrong Format");
System.exit(0);
}
DealCardList dealCardList = new DealCardList(list);
if (!dealCardList.validate()) {
System.out.println("Wrong Format");
System.exit(0);}
在子类中做出方法改进即可,例如
class Trapezoid extends Shape {
private double topSide;
private double bottomSide;
private double height;
public double getTopside() {
return topSide;
}
public void setTopside(double topside) {
this.topSide = topside;
}
public double getBottomside() {
return bottomSide;
}
public void setBottomside(double bottomside) {
this.bottomSide = bottomside;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Trapezoid() {
super();
}
public Trapezoid(double topside, double bottomside, double height) {
super();
this.topSide = topside;
this.bottomSide = bottomside;
this.height = height;
}
public double getArea() {
return (topSide + bottomSide) * height / 2;
}
public boolean validate() {
if (topSide > 0 && bottomSide > 0 && height > 0)
return true;
else
return false;
}
}
第七次的大作业需要熟练的运用封装继承,多态等,其好处分别是
封装意义:防止数据被无意破坏。
如何实现:把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法。
好处: 它所封装的是自己的属性和方法,所以它是不需要依赖其他对象就可以完成自己的操作。
继承好处:继承是使用已存在的类的定义作为基础建立新类的技术,新类的定义可以增加新的数据或新的功能,也可以用父类的功能,但不能选择性地继承父类。通过使用继承我们能够非常方便地复用以前的代码,能够大大的提高开发的效率。
多态好处: 所谓多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
学会这几点就基本能够在编程中较为熟练的应对各种问题。
第八次pta大作业难度非同寻常,从来没见过这么难的作业,拿到这个题人都傻了:编写一个银行 ATM 机的模拟程序,能够完成用户的存款、取款以及查询余额功能。
这完全不会啊。经过多方讨教终于有了一点突破。尝试使用面向对象技术对银行用户在 ATM 机上进行相关操作的模拟系统设计,上述的相关概念均要设计为实体类,业务(控制)类请自行根据实际需要进行扩充和完善。首先面临的问题就是:每一行输入一次业务操作,可以输入多行,最终以字符#终止。需要明确输入终止的方法,并且对输入做出判断是那种类型
while(!input.equals("#")) {
String []arry=deal(input);
if(arry.length==1) {
if(banklist.check(arry[0])!=null){
System.out.println(banklist.check(arry[0]).father.getmoney());
}else{
System.out.println("Sorry,this card does not exist.");
System.exit(0);
};
}else {
if(arry.length==4) {
if(banklist.check(arry[0])==null) {;
System.out.println("Sorry,this card does not exist.");
System.exit(0);
}else {
account one=banklist.check(arry[0]);
if(!arry[1].equals(one.father.password)) {
System.out.println("Sorry,your password is wrong.");
System.exit(0);
}else {
if(!banklist.idexit(arry[2])) {
System.out.println("Sorry,the ATM‘s id is wrong.");
System.exit(0);
}else {
if(one.father.money-Double.parseDouble(arry[3])<0) {
System.out.println("Sorry,your account balance is insufficient.");
System.exit(0);
}else {
if(!one.father.mybank.idexist(arry[2])) {
System.out.println("Sorry,cross-bank withdrawal is not supported.");
}else {
one.descripe(Double.parseDouble(arry[3]),arry[2]);
}
}
}
}
}
}
}
input=in.nextLine();
}
其中需要注意的几个问题是:
1, 务必注意本题目中的各实体类之间的关系,尤其是一对多的组合关系。
2, 对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。
3, 编程时考虑面向对象中的封装性本题目中的应用以及是否有能够扩展的衍生需求。
注意要确保new对象的正确性。
通过所需要的几个类:银行(Bank),银行用户(Person),银行账户(Account),银行卡(Card)完成功能取款和查询。
其中特别需要注意的是List<String> list=new ArrayList<String>()
接口,可以将对象的使用标准化,即面向接口编程。父类为接口,规定使用的方法;子类为各种不同的具体实现,根据实际需求选用不同的实现。
若在最初编写代码时选用ArrayList,而随着需求变更需要替换成LinkedList。使用List<String> list=new ArrayList<String>()创建list,在改变list的实现时(从ArrayList换成LinkedList)只需改变一句话,即List<String> list=new LinkedList<String>(),而对list的调用均无需改变。
例如使用过程中:
class bank{
ArrayList<person> list=new ArrayList<>();
String name;
public bank(ArrayList<person> list, String name, ArrayList<String> numbers) {
super();
this.list = list;
this.name = name;
this.numbers = numbers;
}
public ArrayList<person> getList() {
return list;
}
public void setList(ArrayList<person> list) {
this.list = list;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ArrayList<String> getNumbers() {
return numbers;
}
public void setNumbers(ArrayList<String> numbers) {
this.numbers = numbers;
}
ArrayList<String> numbers=new ArrayList<>();
public bank(String name) {
this.name=name;
if(name.equals("中国建设银行")) {
numbers.add("01");
numbers.add("02");
numbers.add("03");
numbers.add("04");
}
if(name.equals("中国工商银行")) {
numbers.add("05");
numbers.add("06");
}
}
public void addPerson(person one) {
list.add(one);
one.setbank(this);
}
public account check(String id) {
for(int i=0;i<list.size();i++) {
person one=list.get(i);
if(one.check(id)!=null) {
return one.check(id);
};
}
return null;
}
public boolean idexist(String number) {
for(int i=0;i<numbers.size();i++) {
if(numbers.get(i).equals(number)) {
return true;
}
}
return false;
}
}
第九次的作业相对来说较前一次又有一定的难度提升。设计要求:尝试使用面向对象技术对银行用户在 ATM 机上进行相关操作的模拟系统设计,上述的相关概念均要设计为实体类,业务(控制)类请自行根据实际需要进行扩充和完善。
设计一个适当的类图
难度提升的主要部分是是本次作业中银行卡包含借记卡和信用卡两类,且允许跨行办理相关业 务(例如在中国建设银行的 ATM 机上使用中国工商银行的银行卡进行业务操作)。逻辑运算更加复杂。
值得一提的是依旧可以从上次的代码入手进行改进,添加借记卡部分,衔接好各个类之间的关系,修改银行用户得类
class person{
bank mybank;
String name;
String id;
String password;
double money;
public person(bank mybank, String name, String id, String password, double money, ArrayList<account> accounts) {
super();
this.mybank = mybank;
this.name = name;
this.id = id;
this.password = password;
this.money = money;
this.accounts = accounts;
}
public bank getMybank() {
return mybank;
}
public void setMybank(bank mybank) {
this.mybank = mybank;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double getMoney() {
return money;
}
public void setMoney(double money) {
this.money = money;
}
public ArrayList<account> getAccounts() {
return accounts;
}
public void setAccounts(ArrayList<account> accounts) {
this.accounts = accounts;
}
ArrayList<account> accounts=new ArrayList<>();
public person(String name,String password,double money) {
this.name=name;
this.password=password;
this.money=money;
}
public void setbank(bank mybank) {
this.mybank=mybank;
}
public void addmoney(double money) {
this.money=this.money+money*(-1);
}
public void deletemoney(double money) {
this.money=this.money-money;
}
public void addaccount(account one) {
accounts.add(one);
}
public String getmoney() {
//System.out.println("¥"+String.format("%.2f", money));
return "¥"+String.format("%.2f", money);
}
public account check(String id) {
for(int i=0;i<accounts.size();i++) {
if(accounts.get(i).id.equals(id)) {
return accounts.get(i);
}
}
return null;
}
}
需要注意的点是
1、 务必注意本题目中的各实体类之间的关系,尤其是一对多的组合关系。
2、 对实体类的设计要做到单一职责原则,且不能缺少规定的实体类。
3、 在“合成复用原则”及“单一职责原则”基础上,尽量对上次作业的程 序进行重构,使之符合 “开-闭”原则。
最后
总结:
随着学习的深入,每次的题目集在难度上有了提高,这次的三次题目集又增加了类的继承,聚合,多态以及接口引用 。这三次题目集中,更具综合性更有难度的其实是题目集9。这里我谈谈我对聚合和多态的理解:如果类B聚合于类A,那其实是是将B作为类A中的一个属性。
所谓的“多态”,简单的理解就是对象在不同情况下的不同表现,具体体现在定义和功能两个方 面,简单的总结一下,多态可以用“三个定义和两个方法”来总结。三个定义分别是父类定义子类构 建、接口定义实现类构建和抽象类定义实体类构建,而两个方法分别是方法重载和方法重写。
通过本次题目集的学习,我还了解到了接口,前面也提到过,接口相当于一个完全抽象的抽象类,其中有抽象方法,而接口和抽象类一个重要的区别就是接口中只有抽象方法和常量,但接口可以进行多继承,这是两者的区别,使用接口可以提高代码的可维护性和扩展性,且接口可以减少代码的书写,学会使用接口对我们专业的学习非常有帮助。我现在还只了解接口的大概,还需要进一步地去学习接口。