
物件導向程式設計 (OOP) - Composition, Encapsulation 和 Polymorphism
Encapsulation
- Encapsulation 是一個允許你對正在創建的 Objects 裡面的特定 Components 做限制存取的機制。
- 它可以用來屏蔽其它 Class 的存取,保持內部工作正常,且可以讓你修改內容的時候避免損壞。
- 用一個範例來了解 Encapsulation
- 新增 Player.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Player {
public String name;
public int health;
public String weapon;
public void loseHealth(int damage) {
this.health = this.health - damage;
if (this.health <= 0) {
System.out.println("Player knocked out");
// Reduce number of lives remaining for the player
}
}
public int healthRemaining() {
return this.health;
}
}- 修改 Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13Player player = new Player();
player.name = "Vincent";
player.health = 20;
player.weapon = "Sword";
int damage = 10;
player.loseHealth(damage);
System.out.println("Remaining health = " + player.healthRemaining());
damage = 11;
player.health = 200;
player.loseHealth(damage);
System.out.println("Remaining health = " + player.healthRemaining());- 這時候,如果把 Player.java 裡面的
public String name;
改成public String fullName
,整個程式碼就會出錯。 - 新增一個 EnhancedPlayer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class EnhancedPlayer {
private String name;
private int health = 100;
private String weapon;
public EnhancedPlayer(String name, int health, String weapon) {
this.name = name;
if (health > 0 && health <= 100) {
this.health = health;
}
this.weapon = weapon;
}
public void loseHealth(int damage) {
this.health = this.health - damage;
if (this.health <= 0) {
System.out.println("Player knocked out");
// Reduce number of lives remaining for the player
}
}
public int getHealth() {
return health;
}
}- 修改 Main.java
1
2EnhancedPlayer player = new EnhancedPlayer("Vincent", 200, "Sword");
System.out.println("Initial health is " + player.getHealth());- 就算把 health 改成 hitPoints,運作仍然正常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26public class EnhancedPlayer {
private String name;
private int hitPoints = 100;
private String weapon;
public EnhancedPlayer(String name, int health, String weapon) {
this.name = name;
if (health > 0 && health <= 100) {
this.hitPoints = health;
}
this.weapon = weapon;
}
public void loseHealth(int damage) {
this.hitPoints = this.hitPoints - damage;
if (this.hitPoints <= 0) {
System.out.println("Player knocked out");
// Reduce number of lives remaining for the player
}
}
public int getHealth() {
return hitPoints;
}
}
Encapsulation 挑戰
- 題目
Create a class and demonstrate proper encapsulation techniques
the class will be called Printer
It will simulate a real Computer Printer
It should have fields for the toner Level, number of pages printed, and
also whether its a duplex printer (capable of printing on both sides of the paper).
Add methods to fill up the toner (up to a maximum of 100%), another method to
simulate printing a page (which should increase the number of pages printed).
Decide on the scope, whether to use constructors, and anything lese you think is needed. - 答案
- 新增 Printer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public class Printer {
private int tonerLevel = -1;
private int pagesPrinted = 0;
private boolean duplex;
public Printer(int tonerLevel, boolean duplex) {
if (tonerLevel > -1 && tonerLevel <= 100) {
this.tonerLevel = tonerLevel;
}
this.duplex = duplex;
}
public int addToner(int tonerAmount) {
if (tonerAmount > 0 && tonerAmount <= 100) {
if (tonerLevel + tonerAmount > 100) {
return -1;
}
return tonerLevel += tonerAmount;
} else {
return -1;
}
}
public int printPages(int pages) {
int pagesToPrint = pages;
if (duplex) {
System.out.println("Printing in duplex mode");
pagesToPrint = (pages / 2) + (pages % 2);
}
pagesPrinted += pagesToPrint;
return pagesToPrint;
}
public int getPagesPrinted() {
return pagesPrinted;
}
}- 修改 Main.java
1
2
3
4
5
6
7Printer printer = new Printer(50, true);
System.out.println(printer.addToner(50));
System.out.println("initial page count = " + printer.getPagesPrinted());
int pagesPrinted = printer.printPages(4);
System.out.println("Pages printed was " + pagesPrinted + " new total print count for printer = " + printer.getPagesPrinted());
pagesPrinted = printer.printPages(2);
System.out.println("Pages printed was " + pagesPrinted + " new total print count for printer = " + printer.getPagesPrinted());
Polymorphism
- 在 Main.java 新增很多 Class
1 | class Movie { |
- 修改 Main.java 最主要的內容來展示 Polymorphism
1 | public class Main { |
Polymorphism 挑戰
-
題目
We are going to go back to the car analogy.
Crate a base class called Car
It should have a few fields that would be appropriate for a generic car class.
engine, cylinders, wheels, etc.
Constructor should initialize cylinders (number of) and name, and set wheels to 4
and engine to true. Cylinders and names would be passed parameters.
Create appropriate getters
Create some methods like startEngine, accelerate, and brake
show a message for each in the base class
Now create 3 sub classes for your favorite vehicles.
Override the appropriate methods to demonstrate polymorphism in use.
put all classes in the one java file (this one). -
答案
- 新增 Class 到 Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99class Car {
private boolean engine;
private int cylinders;
private String name;
private int wheels;
public Car(int cylinders, String name) {
this.engine = true;
this.cylinders = cylinders;
this.name = name;
this.wheels = 4;
}
public String startEngine() {
return "Car -> startEngine()";
}
public String accelerate() {
return "Car -> accelerate()";
}
public String brake() {
return "Car -> brake()";
}
public int getCylinders() {
return cylinders;
}
public String getName() {
return name;
}
}
class Mitsubishi extends Car {
public Mitsubishi(int cylinders, String name) {
super(cylinders, name);
}
@Override
public String startEngine() {
return "Mitsubishi -> startEngine()";
}
@Override
public String accelerate() {
return "Mitsubishi -> accelerate()";
}
@Override
public String brake() {
return "Mitsubishi -> brake()";
}
}
class Holden extends Car {
public Holden(int cylinders, String name) {
super(cylinders, name);
}
@Override
public String startEngine() {
return "Holden -> startEngine()";
}
@Override
public String accelerate() {
return "Holden -> accelerate()";
}
@Override
public String brake() {
return "Holden -> brake()";
}
}
class Ford extends Car {
public Ford(int cylinders, String name) {
super(cylinders, name);
}
@Override
public String startEngine() {
return "Ford -> startEngine()";
}
@Override
public String accelerate() {
return "Ford -> accelerate()";
}
@Override
public String brake() {
return "Ford -> brake()";
}
}- 修改 Main.java 的主要內容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24public class Main {
public static void main(String[] args) {
Car car = new Car(8, "Base Car");
System.out.println(car.startEngine());
System.out.println(car.accelerate());
System.out.println(car.brake());
Mitsubishi mitsubishi = new Mitsubishi(6, "Outlander VRX 4WD");
System.out.println(mitsubishi.startEngine());
System.out.println(mitsubishi.accelerate());
System.out.println(mitsubishi.brake());
Ford ford = new Ford(6, "Ford Falcon");
System.out.println(ford.startEngine());
System.out.println(ford.accelerate());
System.out.println(ford.brake());
Holden holden = new Holden(6, "Holden Commodore");
System.out.println(holden.startEngine());
System.out.println(holden.accelerate());
System.out.println(holden.brake());
}
}- 可以使用內建語法 getClass().getSimpleName() 來取得 Class 的名稱
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class Mitsubishi extends Car {
public Mitsubishi(int cylinders, String name) {
super(cylinders, name);
}
@Override
public String startEngine() {
return getClass().getSimpleName() + " -> startEngine()";
}
@Override
public String accelerate() {
return getClass().getSimpleName() + " -> accelerate()";
}
@Override
public String brake() {
return getClass().getSimpleName() + " -> brake()";
}
}
OOP 終極挑戰
- 題目
The purpose of this application is to help a company called Bill’s Burgers manage the process of selling their hamburgers. And in order to match Bill’s menu, you will need to create three(3) classes, Hamburger, DeluxeBurger, and HealthyBurger.
For the base Hamburger class, there will need to be four variables to represent the four basic ingredients of the hamburger, name, meat, price, and breadRollType. The price variable should be of type double, while the other three are of type String. A constructor will be needed to accept these four values as parameters when creating a new hamburger.
There will also need to be separate variables for four(4) possible additions to the hamburger. Those should be declared with these names: addition1Name, addition1Price, addition2Name, addition2Price, addition3Name, addition3Price, addition4Name, and addition4Price. The name variables should be of type String and the price variables should be of type double.
Five(5) methods are also needed inside the Hamburger class. Four(4) for adding up to four additions to the hamburger and one(1) for printing out an itemized listing of the final hamburger with addons, if any, and the total price. Remember that a name and price must be accepted as parameters in the first four methods so that the price of the hamburger is adjusted accordingly. These methods should be named addHamburgerAddition1, addHamburgerAddition2, addHamburgerAddition3, addHamburgerAddition4, and itemizeHamburger. The first four methods do not return values, but the last method does return the total price of the hamburger of type double, which includes the base price of the hamburger plus any additional items.
For the second class, DeluxeBurger, there are no additional member variables, and the constructor accepts no parameters. Instead, the constructor creates a deluxe burger with all the fixings and chips and a drink for a base price of $19.10. The constructor can be configured in any way, as long as chips and drink are added for the total price just mentioned. In this class, the four(4) methods defined in the Hamburger class for including additional toppings must each be overridden so that a message is printed stating that no additional items can be added to a deluxe burger.
And for the third class, HealthyBurger, there will be four(4) additional member variables called healthyExtra1Name, healthyExtra1Price, healthyExtra2Name, and healthyExtra2Price. The names are type String and the prices are type double. The constructor for this class accepts two(2) parameters for meat and price. Those are set in the constructor along with an appropriate name for the type of burger.
Two methods, addHealthyAddition1 and addHealthyAddition2 should be created that each accept a name and price for the addition, allowing for up to two(2) addons to the basic healthy burger. And finally the itemizeHamburger method created in the Hamburger class should be overridden to generate a message appropriate to the type of burger along with any addons. The method also returns the total price of the healthy burger of type double.
Example input:Example output:1
2
3
4
5
6
7
8
9
10
11
12
13
14Hamburger hamburger = new Hamburger("Basic", "Sausage", 3.56, "White");
hamburger.addHamburgerAddition1("Tomato", 0.27);
hamburger.addHamburgerAddition2("Lettuce", 0.75);
hamburger.addHamburgerAddition3("Cheese", 1.13);
System.out.println("Total Burger price is " + hamburger.itemizeHamburger());
HealthyBurger healthyBurger = new HealthyBurger("Bacon", 5.67);
healthyBurger.addHamburgerAddition1("Egg", 5.43);
healthyBurger.addHealthyAddition1("Lentils", 3.41);
System.out.println("Total Healthy Burger price is " + healthyBurger.itemizeHamburger());
DeluxeBurger db = new DeluxeBurger();
db.addHamburgerAddition3("Should not do this", 50.53);
System.out.println("Total Deluxe Burger price is " + db.itemizeHamburger());1
2
3
4
5
6
7
8
9
10
11
12
13
14Basic hamburger on a White roll with Sausage, price is 3.56
Added Tomato for an extra 0.27
Added Lettuce for an extra 0.75
Added Cheese for an extra 1.13
Total Burger price is 5.71
Healthy hamburger on a Brown rye roll with Bacon, price is 5.67
Added Egg for an extra 5.43
Added Lentils for an extra 3.41
Total Healthy Burger price is 14.51
Cannot not add additional items to a deluxe burger
Deluxe hamburger on a White roll with Sausage & Bacon, price is 14.54
Added Chips for an extra 2.75
Added Drink for an extra 1.81
Total Deluxe Burger price is 19.10 - 答案
- 新增 Hamburger.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68public class Hamburger {
private String name;
private String meat;
private double price;
private String breadRollType;
private String addition1Name;
private double addition1Price;
private String addition2Name;
private double addition2Price;
private String addition3Name;
private double addition3Price;
private String addition4Name;
private double addition4Price;
public Hamburger(String name, String meat, double price, String breadRollType) {
this.name = name;
this.meat = meat;
this.price = price;
this.breadRollType = breadRollType;
}
public void addHamburgerAddition1(String name, double price) {
this.addition1Name = name;
this.addition1Price = price;
}
public void addHamburgerAddition2(String name, double price) {
this.addition2Name = name;
this.addition2Price = price;
}
public void addHamburgerAddition3(String name, double price) {
this.addition3Name = name;
this.addition3Price = price;
}
public void addHamburgerAddition4(String name, double price) {
this.addition4Name = name;
this.addition4Price = price;
}
public double itemizeHamburger() {
double hamburgerPrice = this.price;
System.out.println(this.name + " hamburger on a " + this.breadRollType + " roll with " + this.meat + ", price is " + this.price);
if (this.addition1Name != null) {
hamburgerPrice += this.addition1Price;
System.out.println("Added " + this.addition1Name + " for an extra " + this.addition1Price);
}
if (this.addition2Name != null) {
hamburgerPrice += this.addition2Price;
System.out.println("Added " + this.addition2Name + " for an extra " + this.addition2Price);
}
if (this.addition3Name != null) {
hamburgerPrice += this.addition3Price;
System.out.println("Added " + this.addition3Name + " for an extra " + this.addition3Price);
}
if (this.addition4Name != null) {
hamburgerPrice += this.addition4Price;
System.out.println("Added " + this.addition4Name + " for an extra " + this.addition4Price);
}
return hamburgerPrice;
}
}- 新增 DeluxeBurger.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27public class DeluxeBurger extends Hamburger {
public DeluxeBurger() {
super("Deluxe", "Sausage & Bacon", 14.54, "White");
super.addHamburgerAddition1("Chips", 2.75);
super.addHamburgerAddition2("Drink", 1.81);
}
@Override
public void addHamburgerAddition1(String addition1Name, double addition1Price) {
System.out.println("Cannot not add additional items to a deluxe burger");
}
@Override
public void addHamburgerAddition2(String addition2Name, double addition2Price) {
System.out.println("Cannot not add additional items to a deluxe burger");
}
@Override
public void addHamburgerAddition3(String addition3Name, double addition3Price) {
System.out.println("Cannot not add additional items to a deluxe burger");
}
@Override
public void addHamburgerAddition4(String addition4Name, double addition4Price) {
System.out.println("Cannot not add additional items to a deluxe burger");
}
}- 新增 HealthyBurger.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36public class HealthyBurger extends Hamburger {
private String healthyExtra1Name;
private double healthyExtra1Price;
private String healthyExtra2Name;
private double healthyExtra2Price;
public HealthyBurger(String meat, double price) {
super("Healthy", meat, price, "Brown rye");
}
public void addHealthyAddition1(String name, double price) {
this.healthyExtra1Name = name;
this.healthyExtra1Price = price;
}
public void addHealthyAddition2(String name, double price) {
this.healthyExtra2Name = name;
this.healthyExtra2Price = price;
}
@Override
public double itemizeHamburger() {
double hamburgerPrice = super.itemizeHamburger();
if (this.healthyExtra1Name != null) {
hamburgerPrice += this.healthyExtra1Price;
System.out.println("Added " + this.healthyExtra1Name + " for an extra " + this.healthyExtra1Price);
}
if (this.healthyExtra2Name != null) {
hamburgerPrice += this.healthyExtra2Price;
System.out.println("Added " + this.healthyExtra2Name + " for an extra " + this.healthyExtra2Price);
}
return hamburgerPrice;
}
}- 修改 Main.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class Main {
public static void main(String[] args) {
Hamburger hamburger = new Hamburger("Basic", "Sausage", 3.56, "White");
hamburger.addHamburgerAddition1("Tomato", 0.27);
hamburger.addHamburgerAddition2("Lettuce", 0.75);
hamburger.addHamburgerAddition3("Cheese", 1.13);
System.out.println("Total Burger price is " + hamburger.itemizeHamburger());
HealthyBurger healthyBurger = new HealthyBurger("Bacon", 5.67);
healthyBurger.addHamburgerAddition1("Egg", 5.43);
healthyBurger.addHealthyAddition1("Lentils", 3.41);
System.out.println("Total Healthy Burger price is " + healthyBurger.itemizeHamburger());
DeluxeBurger db = new DeluxeBurger();
db.addHamburgerAddition3("Should not do this", 50.53);
System.out.println("Total Deluxe Burger price is " + db.itemizeHamburger());
}
}