Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
หลกการออกแบบ
• ชอคลาสตองเปนค านาม
• ชอคลาสตองสอใหเรารวาจะท าอะไรกบออบเจกตของคลาสนนไดบาง– ตวอยาง ถาท าโปรแกรมเกยวกบการจายเงนเดอน เราไมควรสรางคลาสคลาสเดยวทท าทกอยาง อยาง PaycheckProgram
– แตเราควรเขยน Paycheck ขนมา แลวนยามเมธอดทเปลยนคาหรอจดการ Paycheck ได แลวจงน า Paycheck ออบเจกตไปใชในคลาสทเรารน main
• ถาเกดคลาสมเมธอดทท าหนาทไมคอยเกยวของกน เราควรแยกคลาสนนออกเปนสองคลาส ใหแตละคลาสเรยกเมธอดทเกยวกนภายในคลาสเทานน– ท าใหโปรแกรมดงายขน แกงายขน
– แตวาคลาสหนงจะตองใชอกคลาสหนง ถามมากๆอาจเปนปญหา
– ดงนนใหแยกคลาสเทาทจ าเปนเทานน
Immutable class• เปนคลาสทมแต accessor เมธอดเทานน
– ตวอยางคอ String เมอออบเจกตทเปน String ถกสรางขนมาแลว จะไมมวนเปลยน เพราะไมมเมธอดในคลาส String ทจะเปลยนคาอะไรของString ออบเจกตไดเลย
String name = “John”;
String uppercase = name.toUpperCase(); // name ไมเปลยนนะ
• ขอดของคลาสประเภทนคอ เอา ref ของออบเจกตใหคนอนใชงานไดโดยไมตองกงวลวาคาจะเปลยน
Side effect• เมธอดทม side effect คอ เมธอดทโคดของมนเปลยนคาทมองเหนไดแมวาเมธอดจะรนเสรจไปแลว เชน คาของ instance variable
ตวอยางเชน public class BankAccount{
….
public void transfer(double amount, BankAccount other){
balance = balance –amount;
other.deposit(amount);
}
}
เปลยนคาตวแปรใน this
เปลยนคาตวแปรในออบเจกตอกตวดวย
ขอควรระวง
• ถาใชออบเจกตเปนพารามเตอรของเมธอด เราเปลยนคาภายในออบเจกตนนได การเปลยนแปลงจะยงอยแมวาเมธอดจะรนเสรจแลว
• แตวา ถาพารามเตอรของเมธอดเปน primitive type เราจะเปลยนคายงไง กจะมผลอยแคในเมธอดเทานน
• ดตวอยาง
• สมมตเราเปลยนเมธอด transfer เปนแบบน public void transfer(double amount, double otherBalance){
balance = balance –amount;
otherBalance = otherBalance + amount;
}
แลวไปเรยกใชงานแบบน
double savingBalance = 1000;
myAccount.transfer(500,savingBalance);
System.out.println(savingBalance);
ตอนเขาไปรนเมธอด มนจะถอวารบคาเขาไปเทานน ตวตนฉบบไมเปลยน
อยาใชพารามเตอรเปนททด
• ถงเราจะรวา พารามเตอรในเมธอด ทเปน primitive type นน จะไมมผลกบภายนอก แตกไมควรใชมนเปนททด
public void deposit(double amount){
amount = balance + amount;
…
} อยางนจะท าใหพารามเตอรทเราเอาเขามา เปลยนคา ท าใหใชคาผดจากทตองการไดภายในเมธอดน ท าใหเพอนทมาใชโปรแกรมเราตอสบสนดวย
ถาตองการทด สราง local variable ขนมาใหมภายในเมธอดเลยดกวา
ขอควรระวงอกอยาง• ระวงจะลบหรอเปลยนขอมลทไมสมควรเปลยน เชน
public class GradeBook{
public void addStudents(ArrayList<String> names){
while(names.size()>0){
String a_name = names.remove(0);
add(a_name);
}
}
}
ตวอารเรยลสตตนฉบบจะถกลบดวย ดงนนจะเอาไปใชงานทอนในโปรแกรมอกไมไดแลว
ขางลางนผด เพราะอะไร?
public class BankAccount{
….
public void transfer(double amount, BankAccountother){
balance = balance –amount;
double newBalance = other.balance +amount;
other = new BankAccount(newBalance);}
}
a.transfer(100,b);a
b
balance = 500
balance = 500
ตอนเมธอดรน จะรบ ref ของ b เขาไป ท าใหเกดอก ref ขนมา
other a
b
balance = 400
balance = 500
other balance = 600
this
สรปวา b ไมเปลยนเลยถาเขยนแบบน
precondition
• คอสงทตองเปนจรงกอนทเมธอดจะถกเรยกใช ถาไมเปนจรง เจงแน
• เชน เมธอด deposit ตองรบเลขทไมเปนลบเทานน• ตามปกต ควรจะเขยนเปนสวนหนงของคอมเมนไว จะไดเอาไวเชค
/**Deposit money tothe bank account.@param amount the amount to deposit(Precondition: amount >=0)
*/
public void deposit(double amount){…}
• ถาเมธอดถกเรยกโดยท precondition ของมนยงไมเปนจรง– เราอาจตรวจแลว throw exception ได (เดยวไดเรยนเอง)– หรอเราอาจปลอยเลยตามเลย เพราะถอวาคนเรยกเมธอดผดเองทไมไดเรยกตาม precondition
– เดยวกอน ยงมอกวธส าหรบ java
assertion
Public double deposit(double amount){
assert amount >= 0;
balance = balance + amount;
}
สามารถสง enable/disable ได ท าใหแยกสวนนออกจากโปรแกรมได
ถา enable อย แลวได false โปรแกรมจะหยดท างาน แลว throw AssertionError
Java –ea MainClass
• ท าให error ชดเจนแบบน จะไดรตววาเขยนผด และรบแก
• ดกวามา if แลว return กลบ โดยไมท าอะไร เพราะอนนคนรนจะไมเหนวาโปรแกรมผดเลย
postcondition
• ไดคา return value ทถกตอง• ออบเจกตเปลยนไปตามทตองการ/**
Deposit money tothe bank account.(Postcondition: getBalance() >= 0)@param amount the amount to deposit(Precondition: amount >=0)
*/
public void deposit(double amount){…}
Class invariant
• คอสงทเปนจรงเสมอหลงจากสรางออบเจกตแลว ไมวาเมธอดอะไรจะโดนเรยกกเปนจรงอย
• ถาเรารวา class invariant คออะไร เรากตรวจโปรแกรมเราไดวาขณะนนเขยนถกอยหรอไม
public class BankAccount{
double balance;
/**Construct a bank account with a given balance.@param initialBalance the money in the account at the time it is open.(Precondition: initialBalance >=0)
*/public BankAccount(double initialBalance){
balance = initialBalance;}
/**Deposit money tothe bank account.(Postcondition: getBalance() >= 0)@param amount the amount to deposit(Precondition: amount >=0)
*/
public void deposit(double amount){…}
มาดโคดของ BankAccount กนอกท
/**Withdraws money from the bank account.@param amount the amount to withdraw
*/
public void withdraw(double amount){…}
/**Gets the current balance of the bank account.@return the current balance
*/
public double getBalance(){…}
• เราสงเกตไดวา ตงแตสรางออบเจกต คา getBalance() >= 0 เสมอแนนอน ดจากprecondition ของทกเมธอด แลวกสงเกตดดวยวา หลงจากแตและเมธอดถกเรยกแลว ยงเปนจรงอยหรอเปลา
• เอาคา invariant นไปเขยนบรรยายเปนคอมเมนซะ
/**
…
(Invariant: getBalance() >= 0)
*/public class BankAccount{…}
Static method
• ไมตองสรางออบเจกต กเรยกใชไดเลย เชนเมธอดใน utility class อยาง Math
• สรางขนเพอลดการเขยนโคด อยางทเรยนตอนปหนงนนแหละ แตเมธอดแบบนจะไมตองใชเปลยนหรออานคาของออบเจกตไง
• หลายๆเมธอดเปน static เพราะวามนเลนกบ primitive type เชนตวเลข ซงเราสรางออบเจกตไมได
• เรยกเมธอดประเภทน ตองเรยกจากการใชชอคลาส
การใชงานอกอยางของ static method
• ใชเมอเราไมตองการเปลยนคลาสทมอยแลว หรอเปลยนคลาสทมอยแลวไมได
public class Geometry{
public static double area(Rectangle rect){
return rect.getWidth()*rect.getHeight();
}
} เปนของจาวา เราเปลยนไมได เลยรบเปนพารามเตอรของเมธอดของคลาสใหมแทน ใหเมธอดเปน static เพราะเรามออบเจกตอยแลว คอตว Rectangle
วธ initialize static variable
• ไมท าอะไร มนกมคา default เอง
• Assign คา ตอนทเรา declare มนprivate static int x = 1000;
• อกวธคอใช static initialization block
Static import
import static java.lang.System.*;
import static java.lang.Math.*;
double r = sqrt(PI);
out.println(r);
ท าใหไมตองเขยนยาว และโคดอานงายขน
วธ initialize instance variable• ใชคา default
• ใช constructor
• เขยนคา default เอง ตอน declare ตวแปรนน
public class Coin{
private double value =1;
…
}
คานจะเปน default ตอนสรางทกออบเจกตของคลาสน