今天要了解OOP(面向對象程序)
Class(類) 可以想像成製造的樣本藍圖
例如、車 Class
把構成車的基本要素 抽出 即是 類
又可以分成variable(狀態)跟 method(動作)
輪子(狀態)車門 (狀態)品牌(狀態) 價格(狀態)
能前進(動作) 能後退(動作)
當我們要用到 某一台特定的車時 就可以從這個類中 創出一個新對象
檔案:Car.java
public class Car { private int doors;
private int wheels;
private String model;
private String engine;
public String color;}
private 無法從外部訪問
public 可以從外部訪位
檔案:Main.java
public class Main { public static void main(String[] args) {
Car toyota = new Car();
toyota.model = "AE86";
toyota.color = "BlackAndWhite";
toyota.wheels = 4; // error :wheels' has private access in 'Car'
}
}
可以看到 從Class Car中
new出一個 Toyota的AE86
但wheel 因為是private 就無法修改賦值
如果要修改賦值
在Car.java中
創造一個method 來修改
private int wheels;
public void setWheels(Integer wheels){
this.wheels = wheels;
}
此時在Main.java中
就可以調用此method來修改
public static void main(String[] args) {
toyota.setWheels(6);
}
同理,如果要取得數據
創造一個motod來取得
public int getWheels(){
return this.wheels;
}
調用
System.out.println(toyota.model + " has " + toyota.getWheels() + " wheels");
toyota.setWheels(6);
System.out.println(toyota.model + " has " + toyota.getWheels() + " wheels");
輸出:
AE86 has 0 wheels
AE86 has 6 wheels
第一句是0,因為還沒有調用賦值的method
第二句有數字,是因為已經賦值過了
為啥要搞那麼麻煩?
因為設private的variable=filed就不能讓使用者亂搞
例如,若要把wheel設定成 -50,
一台車的輪子怎可能是負的,顯然不合理。
所以能在此method加入if規則,通過驗證的數據才能賦值。
public void setWheels(Integer wheels) {
if (wheels > 20 || wheels < 1) {
System.out.println("Dude, are you sure that is car?");
} else {
this.wheels = wheels;
System.out.println("Dude, nice wheels.");
}
調用:
toyota.setWheels(-50);
toyota.setWheels(8);
輸出:
Dude, are you sure that is car?
Dude, nice wheels.
這也就是OOP中encapsulation(封裝)的概念
this意思 Bento Lulu同學補充:
this
is a reference to the current object.
Imagine you have a class named Person.
class Person{
String name;
public void setName(String name){
this.name = name;
}
}
There are 2 variables with the name ‘name’, one is an attribute String name;
of the class, so all objects of the class will have a name, and the other is an argument for the method setName(String name)
.
this.name = name;
inside of the method, means that we are giving the value of the name passed as argument to the attribute name, so the value passed will be the name of the object. Is as if this
is taking you out of all methods and make you access the members of the object, in this case String name;
If we create two objects:
Person p1 = new Person();
Person p2 = new Person();
Then assign names to them with the method:
p1.setName("Ben");
//'this' inside this call will point to object p1
p2.setName("Liam");
//'this' inside this call will point to object p2
So ‘this’ means ‘current object’, and there names will be set:
p1 will have name Ben
p2 will have name Liam
例外、stack overflow補充:點此
但這補充我是看不太懂
看同學補充應該就夠
簡單的說 this 就是專指new出來的對應object
小挑戰 bank:
Create a new class for a bank account
Create fields for the account number, balance, customer name, email and phone number.
Create getters and setters for each field
Create two additional methods
1. To allow the customer to deposit funds (this should increment the balance field).
2. To allow the customer to withdraw funds. This should deduct from the balance field,
but not allow the withdrawal to complete if their are insufficient funds.
You will want to create various code in the Main class (the one created by IntelliJ) to
confirm your code is working.
Add some System.out.println’s in the two methods above as well.
參考答案:
小挑戰 bank
public class Bank { private int accountNumber;
private double balance;
private String customerName;
private String email;
private int phoneNumber; public static void main(String[] args) {
Bank westdoor = new Bank();
westdoor.deposit(500);
System.out.println(westdoor.getBalance());
westdoor.withdraw(600);
westdoor.withdraw(250);
System.out.println(westdoor.getBalance()); } public int getAccountNumber() {
return accountNumber;
} public void setAccountNumber(int accountNumber) {
this.accountNumber = accountNumber;
} public double getBalance() {
return balance;
} public void setBalance(double balance) {
this.balance = balance;
} public String getCustomerName() {
return customerName;
} public void setCustomerName(String customerName) {
this.customerName = customerName;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public int getPhoneNumber() {
return phoneNumber;
} public void setPhoneNumber(int phoneNumber) {
this.phoneNumber = phoneNumber;
} public void deposit(double money) {
this.setBalance(this.getBalance() + money);
} public void withdraw(int money) {
if (money > this.getBalance()) {
System.out.println("Not enough");
} else this.setBalance(this.getBalance() - money);
}
}
輸出結果:
500.0
Not enough
250.0
以這個銀行代碼為例
若有人要開戶
就要在前面set5次
檔案:Main.java
Bank rich = new Bank();
rich.setAccountNumber(999777888);
rich.setBalance(87654);
rich.setCustomerName("Ben");
rich.setEmail("Ben@gmail.com");
rich.setPhoneNumber(12354321);
若是有20個資料的話,那起不是要set20次
自然不用如此,
在class Bank中創一個同名Method。
此時呼叫new Bank()
之時,也就會第一個執行
那後面的5個set,也就不用另外寫了,可以在直接當作參數傳入
檔案:Bank.java
public class Bank { private int accountNumber;
private double balance;
private String customerName;
private String email;
private int phoneNumber; public Bank(int accountNumber, double balance, String customerName, String email, int phoneNumber) {
System.out.println("Second execute");
this.accountNumber = accountNumber;
this.balance = balance;
this.customerName = customerName;
this.email = email;
this.phoneNumber = phoneNumber;
} public Bank() {
System.out.println("First execute");
}
輸出結果:
First execute
— -
檔案:Main.java
修改成一行,並測試有無傳入進去。
Bank rich = new Bank(999777888, 87654, "Ben", "Ben@gmail.com", 12354321);
System.out.println(rich.getAccountNumber());
輸出結果:
Second execute
999777888
— -
那如果用戶忘記傳入參數,系統一定要個預設起始值怎辦?
檔案:Bank.java
public class Bank { private int accountNumber;
private double balance;
private String customerName;
private String email;
private int phoneNumber; public Bank(int accountNumber, double balance, String customerName, String email, int phoneNumber) {
System.out.println("Second execute");
this.accountNumber = accountNumber;
this.balance = balance;
this.customerName = customerName;
this.email = email;
this.phoneNumber = phoneNumber;
} public Bank() {
this(8888888, 00.00, "Defaault customername", "Default email", 12300000);
System.out.println("First execute");
}
檔案:Main.java
Bank rich = new Bank();
System.out.println(rich.getAccountNumber());
輸出結果:
Second execute
First execute
8888888
— -
這裡就用到之前提到過的Overlo技巧
可以寫好幾個方法,不管用戶傳入幾個參數,都有對應的method來執行
這裡要注意的是,new Bank()
call的是沒有參數的Bank()
所以先執行的並不是像輸出結果的Second execute那段
而是因為this(8888888, 00.00, "Defaault customername", "Default email", 12300000)
這段
才去執行了有參數的Bank()
等於在這個沒有參數的method中,去呼叫了另一個帶參數的method。
在Bank(無參數)之中呼叫了Bank(全參數)
小挑戰 — VipCustomer
Create a new class VipCustomer
it should have 3 fields name, credit limit, and email address.
create 3 constructors
1st constructor empty should call the constructor with 3 parameters with default values
2nd constructor should pass on the 2 values it receives and add a default value for the 3rd
3rd constructor should save all fields.
create getters only for this using code generation of intellij as setters wont be needed
test and confirm it works.
參考答案 VipCustomer
Vip_Customer.java
public class Vip_Customer { private String name;
private double creditLimit;
private String emailAddress; public Vip_Customer() {
this("Default name", 666, "Defalut email");
} public Vip_Customer(String name, String emailAddress) {
this(name, 666, emailAddress);
} public Vip_Customer(String name, double creditLimit, String emailAddress) {
this.name = name;
this.creditLimit = creditLimit;
this.emailAddress = emailAddress;
System.out.println("Start");
System.out.println("name: " + this.getName() +
"\ncreditLimit: " + this.getCreditLimit() +
"\nemail: " + this.getEmailAddress());
System.out.println("------");
} public String getName() {
return name;
} public double getCreditLimit() {
return creditLimit;
} public String getEmailAddress() {
return emailAddress;
}
}
main.java
public class Main { public static void main(String[] args) {
Vip_Customer rich = new Vip_Customer();
Vip_Customer Tom = new Vip_Customer("Tom", "Tom@gmail.com");
Vip_Customer Kyle = new Vip_Customer("Kyle", 987654, "Kyle@gmail.com"); }
}
輸出結果:
Start
name: Default name
creditLimit: 666.0
email: Defalut email
— — —
Start
name: Tom
creditLimit: 666.0
email: Tom@gmail.com
— — —
Start
name: Kyle
creditLimit: 987654.0
email: Kyle@gmail.com