《Head First Java》笔记(2)

您所在的位置:网站首页 spss中如何筛选数据 《Head First Java》笔记(2)

《Head First Java》笔记(2)

2023-03-14 21:49| 来源: 网络整理| 查看: 265

2.1 面向过程与面向对象之间的战争

面向过程与面向对象之间的战争是由下面一则小故事引起的。

从前,有一个软件小铺,该小铺的老板娘(同时也是项目经历)手下有两个小兵:阿朱和阿娇。有一天,老板娘故意刁难两个兵,并且让她两进行比赛,看谁的程序写的好。要求:在图形接口画出正方形、圆形与三角形。当用户点选某个图形时,图形要顺时针旋转360度,并且根据形状的不同而播放不同的AIF音效的音乐文件。 最终赢的人会坐上象征身份地位的宝座!

当接到这个任务的时候,阿朱首先想到的是:这个程序要执行什么动作?会需要什么样的程序?一会她就想到了,需要旋转(rotate)和播放音乐(playSound)这两个动作。于是,阿朱就迫不及待的写下了下面的程序: 这里写图片描述

当接到这个任务的时候,阿娇首先想到的是:这个程序有什么样的事物?有什么关键角色?她首先想到的时候形状体(shape)。当然,她还想到了用户、声响等对象与点击等事件。但是这些对象早就已经建立好了,而她只需要专注于创建形状体就ok了。于是,她就写下了如下程序: 这里写图片描述

此时,当阿朱看到阿娇的代码这么长的时候,心里已经乐开花了,心想,这次赢定了,那个宝座是自己的了!!!

然而,万恶的老板娘此时却又说规格需要有点改动。在原有的基础上,加上阿米巴原虫形状(不规则形状体),用户点选时也是旋转并播放.hif声音的文件。

听到这个改动后,阿朱心想rotate这个程序还可以接着用,但是playSound这个就得需要修改了,于是,她奋笔写下了如下程序: 这里写图片描述

听到这个改动后,阿娇苦笑一下,在原有的基础上又增加了一个类,如下: 这里写图片描述

当她们两把各自的程序拿给老板娘看时,老板娘失望的说:“唉呀,不对呀,阿米巴原虫不是这样旋转的…..”。 原来两个人都把旋转部分写成了这样: 1) 找出指定形状的外接四边形 2) 计算出外接四边形的中心点,以此点为中心进行旋转。 但是老板娘认为阿米巴原虫是这样旋转的:绕着一端进行旋转。 听到这里,阿朱一脸的懵逼,最后奋力的在rotate函数中加上“if/else”,于是写下了下面的程序: 这里写图片描述

这样做之后,就会造成其有一堆程序需要修改,从而本来已经测试号的东西全部又要重来一遍。

而阿娇仅仅在Amoeda这类上作了相应的修改,其他已经测试通过的部分完全不需要修改。其实现如下: 这里写图片描述

此时,阿朱看到阿娇的改动非常小,心有不甘。于是,就质问道:“阿娇,你写的代码中,冲的部分太多,而且设计的时候需要同时维护4个不同的rotate方法,效率有点低”。面对阿朱的质疑。阿娇不紧不慢的回答道:“阿朱,让我告诉你什么叫做面向对象的继承(inheritance)”。

第一步:找出4个类中的共同部分 这里写图片描述

第二步:它们都是形状(Shape),而且都有rotate和playSound这两个方法,因此可以提取出新的类 这里写图片描述

第三步:将上面的4个不同的形状体以继承的关系连接到Shape这个新类中,如下: 这里写图片描述

我们可以称“Square继承自Shape”,“Circle继承自Shape”,“Triangle继承自Shape”,“Amoeda继承自Shape”,而rotate和playSound这两个方法已经移出了Square、Circle、Triangle和Amoeda这四个类了。这里,我们称Shape这个类为父类(基类),称Square、Circle、Triangle和Amoeda这四个类为子类(派生类)。

到这里,阿朱还不死心,继续提出了质疑:“你这样设计,岂不是阿米巴原虫也是继承自Shape,那旋转的功能不就是都变成一样的了吗?” 阿娇说:“问的号。Amoeda这个类可以覆盖(override)Shape的方法。Java虚拟机会知道在遇到Amoeda时会使用不同的rotate方法。”

第四步:让Amoeda这个类去覆盖Shape这个父类中的rotate()和playSound()的两个方法。 这里写图片描述

覆盖的意思就是由子类重新定义继承下来的方法,以改变或延伸此方法的行为。

到此,你是不是就觉得这场比赛,阿娇大获全胜呢??非也,其实获胜的是阿花(老板娘的侄女)。看到这里,各位看官想必都明白:出来混社会,关系一定要硬啊!!!!

2.2 类与对象

首先要明白:类不是对象,类是用来创建对象的模型

创建对象需要两个类:一个是要被操作于对象的类,另一个是用来测试该类的类。

测试用的类带有main()方法,并且会在其中建立与存取被测的对象。 习惯用法:测试用的类一般命名为“受测类名称”+TestDrive。

下面就来创建第一个对象Dog 第1步:编写被测对象Dog类

class Dog{ //定义实例变量 int size; String breed; String name; //定义方法 void bark() { System.out.println("Ruff ! Ruff !"); } }

第2步:编写测试用的类DogTestDrive

class DogTestDrive{ public static void main(String[] args) { Dog d = new Dog(); //创建一个Dog对象,对象名为d d.size = 40; //采用圆点运算符存取对象的变量 d.bark(); //采用圆点运算符调用对象的方法 }}

命令行中执行命令:(必须在绝对路径下去执行)

>javac DogTestDirve.java>java DogTestDrive

运行结果: 这里写图片描述

2.3 快离开main

只要还待在main中,你就是游离在对象村之外!因为,对于面向对象应用程序来说,我们需要用对象来与对象交互。

2.3.1 main()的两种用途:测试真正的类启动Java应用程序

真正的Java程序只会让对象与对象交互。这里所说的交互是指相互调用方法。

2.3.2 猜数字游戏

游戏规则: 游戏开始先产生一个0~9之间的随机数作为谜底,然后由三个玩家进行猜数字,只要有一个玩家猜的数字与谜底数字相同,游戏就结束,否则一直进行下去。

对象设计: 这里涉及到两个对象:Player(玩家)和Game(游戏),针对游戏规则,我们设计三个类:Player、GuessGame、GuessLauncher,如下: 这里写图片描述

程序源码:

class GuessGame{ public void startGame() { //先创建三个玩家 Player p1 = new Player(); Player p2 = new Player(); Player p3 = new Player(); //定义三个变量,分别存放玩家所猜的数字 int guessP1 = 0; int guessP2 = 0; int guessP3 = 0; //声明三个变量,保存玩家是否猜中 boolean p1isRight = false; boolean p2isRight = false; boolean p3isRight = false; //随机产生一个0~9之间的数作为谜底数字 int targetNumber = (int)(Math.random() * 10); System.out.println("Target Number is " + targetNumber); while(true) { //获取每个玩家所猜的数字 p1.guess(); guessP1 = p1.number; System.out.println("Player one guessed is " + guessP1); p2.guess(); guessP2 = p2.number; System.out.println("Player two guessed is " + guessP2); p3.guess(); guessP3 = p3.number; System.out.println("Player three guessed is " + guessP3); if(guessP1 == targetNumber) { p1isRight = true; } if(guessP2 == targetNumber) { p2isRight = true; } if(guessP3 == targetNumber) { p3isRight = true; } if(p1isRight || p2isRight || p3isRight)//只要有一人猜中,游戏就结束 { System.out.println("We have a winner !"); System.out.println("Player one guessed right ? " + p1isRight); System.out.println("Player two guessed right ? " + p2isRight); System.out.println("Player three guessed right ? " + p3isRight); System.out.println("Game Over"); break; //游戏结束,跳出循环 } else { System.out.println("No one guess right, and game must be continue"); } } }}class Player{ int number = 0; //保存玩家猜的数字 public void guess() { number = (int) (Math.random() * 10); }}public class GameLauncher{ public static void main(String[] args) { GuessGame game = new GuessGame(); game.startGame(); }}

编译遇到的问题: 1> 命令行编译java源文件提示“编码GBK的不可映射字符” 解决方法: 在输入 javac 命令时,额外输入 -encoding utf-8, 例如:如果编译的源文件名为 Test.java ,那么编译时原先只需输入javac Test.java,而现在需要输入 javac -encoding utf-8 Test.java

2> 显示错误 1. 类GuessGame是公共的,应在名为GuessGame.java文件中声明。 2. 类Player是公共的,应在名为Player.java文件中声明 解决方法: 产生上面的错误原因是,将三个类都写在了同一个.java文件中了,并且类的前面都用了public修饰符进行了修饰,而一个.java文件里面只能有一个public class XXX{} 。 所以将GuessGame和Player这两个类前面的public修饰符去掉,或者将这两个类写在不同的.java文件中即可。 运行结果: 这里写图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3