本节书摘来自异步社区《Android游戏开发详解》一书中的第2章,第2.15节改进程序,作者 【美】Jonathan S. Harbour,更多章节内容可以访问云栖社区“异步社区”公众号查看
2.15 改进程序
Android游戏开发详解
让我们记住上面的原理,并且努力地改进程序。首先,添加一个内建的Java关键字private作为所有Phone对象的变量的修饰符,如程序清单2.14第4行到第7行所示。
程序清单2.14 隐藏Phone类中的变量
01 public class Phone {
02
03 // These variables describe the Phone object's state
04 private boolean poweredOn;
05 private boolean playingMusic;
06 private String phoneManufacturer;
07 private double androidVersionNumber;
08
09 // These methods are the Phone object's behaviors
10 void togglePower() {
11 if (poweredOn) {
12 System.out.println("Powering off!");
13 poweredOn = false;
14 playingMusic = false;
15 } else {
16 System.out.println("Powering on!");
17 poweredOn = true;
18 }
19 } // ends togglePower method
20
21 void playMusic() {
22 if (poweredOn) {
23 System.out.println("Playing music!");
24 }
25 } // ends playMusic method
26
27 void upgrade(double newVersion) {
28 if (newVersion > androidVersionNumber) {
29 androidVersionNumber = newVersion;
30 } else {
31 System.out.println("Upgrade failed!");
32 }
33 } // ends upgrade method
34
35 } // ends class
让变量成为private的,意味着其他的类不再能够直接访问它们,也意味着这些变量不再是暴露的了。因此,你将会看到World类中出现错误,如图2-21所示(不能直接引用不同的类中的一个private的变量)。
程序目前有所谓的编译时错误(发生在代码编译过程中的错误,参见图2-18以及后续的介绍)。有编译时错误的程序无法运行。JVM甚至不会接受这种程序。让我们删除引发错误的所有代码行,如程序清单2.15所示(在删除的所有代码行上,都有一条删除线)。
程序清单2.15 World.java——删除错误代码
01 public class World {
02
03 public static void main(String[] args) {
04 System.out.println("Hello, world!");
05 Phone myPhone = new Phone();
06 myPhone.poweredOn = true;
07 myPhone.playingMusic = false;
08 myPhone.phoneManufacturer = "Samsung";
09 myPhone.androidVersionNumber = 4.4;
10
11 System.out.println("myPhone's state:");
12 System.out.println("Powered on: " + myPhone.poweredOn);
13 System.out.println("Playing music: " + myPhone.playingMusic);
14 System.out.println("Manufacturer: " + myPhone.phoneManufacturer);
15 System.out.println("Version: " + myPhone.androidVersionNumber);
16
17 myPhone.togglePower();
18 myPhone.upgrade(4.5);
19
20 // include “\n” to skip a line when printing.
21 System.out.println("\nmyPhone's NEW state:");
22 System.out.println("Powered on: " + myPhone.poweredOn);
23 System.out.println("Playing music: " + myPhone.playingMusic);
24 System.out.println("Manufacturer: " + myPhone.phoneManufacturer);
25 System.out.println("Version: " + myPhone.androidVersionNumber);
26 }
27 }
要执行这一清理工作,我们必须删除程序的两项功能。我们不再能够为Phone对象的变量赋初始值,并且不再能够访问这些变量以打印出它们。我们可以通过在Phone类中提供方法来执行这些任务,从而以更高效的方式来实现这些功能。
让我们给Phone类添加两个新的方法:initialize()和describe(),如程序清单2.16所示,并且为playingMusic和androidVersionNumber变量提供初始值(如程序清单2.16的第5行和第7行所示)。
程序清单2.16 Phone.java——更新版本(新的代码行突出显示)
01 public class Phone {
02
03 // These variables describe the Phone object's state
04 private boolean poweredOn;
05 private boolean playingMusic = false;
06 private String phoneManufacturer;
07 private double androidVersionNumber = 4.4;
08
09 // These methods are the Phone object's behaviors
10 void initialize(boolean poweredOn, String phoneManufacturer) {
11 this.poweredOn = poweredOn;
12 this.phoneManufacturer = phoneManufacturer;
13 }
14
15 void togglePower() {
16 if (poweredOn) {
17 System.out.println("Powering off!");
18 poweredOn = false;
19 playingMusic = false;
20 } else {
21 System.out.println("Powering on!");
22 poweredOn = true;
23 }
24 }
25
26 void playMusic() {
27 if (poweredOn) {
28 System.out.println("Playing music!");
29 }
30 }
31
32 void upgrade(double newVersion) {
33 if (newVersion > androidVersionNumber) {
34 androidVersionNumber = newVersion;
35 } else {
36 System.out.println("Upgrade failed!");
37 }
38 }
39
40 void describe() {
41 System.out.println("\nPhone's state:");
42 System.out.println("Powered on: " + poweredOn);
43 System.out.println("Playing music: " + playingMusic);
44 System.out.println("Manufacturer: " + phoneManufacturer);
45 System.out.println("Version: " + androidVersionNumber);
46 }
47
48 } // ends class
让我们讨论一下describe()方法(程序清单2.16的第40行到第46行)。你注意到,它执行了我们前面在World类中所执行的相同的打印行为。这一次,我们不必使用点运算符,因为可以从同一个类中访问这些变量。
然而,在某些情况下,你确实需要使用点运算符。来进一步看一下initialize()方法(程序清单2.16的第10行到第13行)。
void initialize(boolean poweredOn, String phoneManufacturer) {
this.poweredOn = poweredOn;
this.phoneManufacturer = phoneManufacturer;
}
initialize()方法直接接受两个输入:一个名为poweredOn的boolean值,以及一个名为phoneManufacturer的字符串。这个方法唯一的功能就是,将我们没有为其提供默认值的两个变量poweredOn和phoneManufacturer(还记得吧,我们已经为另外两个变量提供了初始值)初始化。如图2-22所示。
注意,我们在这里确实使用了点运算符。使用this关键字让程序知道,我们引用的是对象的这个实例,即我们在其上调用initialize()方法的当前Phone对象。这就是我们如何区分属于对象的poweredOn变量和属于方法(通过参数而接受)的poweredOn变量。
既然已经创建了两个方法,我们就能够访问Phone对象的私有变量,让我们来修改World类,以便它可以调用这些方法,参见程序清单2.17中高亮显示的第6行、第7行和第10行。
程序清单2.17 World.java——调用新的方法
01 public class World {
02
03 public static void main(String[] args) {
04 System.out.println("Hello, world!");
05 Phone myPhone = new Phone();
06 myPhone.initialize(false, "Samsung");
07 myPhone.describe();
08 myPhone.togglePower();
09 myPhone.upgrade(4.5);
10 myPhone.describe();
11 }
12 }
相应的输出如下所示。
Hello, world!
Phone's state:
Powered on: false
Playing music: false
Manufacturer: Samsung
Version: 4.4
Powering on!
Phone's state:
Powered on: true
Playing music: false
Manufacturer: Samsung
Version: 4.5