295
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
double x=Double.parseDouble(jTextField1.getText());
double y=Double.parseDouble(jTextField2.getText());
jTextField3.setText(String.valueOf(c.minus(x, y)));
}
--------------------------------------------------------------------------------------------------------------------
ป่ มุ *
private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
double x=Double.parseDouble(jTextField1.getText());
double y=Double.parseDouble(jTextField2.getText());
jTextField3.setText(String.valueOf(c.multiply(x, y)));
}
--------------------------------------------------------------------------------------------------------------------
ป่ มุ /
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
double x=Double.parseDouble(jTextField1.getText());
double y=Double.parseDouble(jTextField2.getText());
jTextField3.setText(String.valueOf(c.divide(x, y)));
}
--------------------------------------------------------------------------------------------------------------------
ป่ ุมปิ ด
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
System.exit(0);
}
--------------------------------------------------------------------------------------------------------------------
ส่วนท้าย
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JButton jButton4;
296
private javax.swing.JButton jButton5;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JTextField jTextField1;
private javax.swing.JTextField jTextField2;
private javax.swing.JTextField jTextField3;
--------------------------------------------------------------------------------------------------------------------
ผลการรันโปรแกรมจะได้ตามที่ออกแบบไว้ โดยท่ี คุณสมบตั ิดังกล่าวน้ีสามารถสร้างส่วนการ
ติดต่อใหม้ ีความยดื หยนุ่ ไดม้ ากข้ึน
ตัวอย่างท่ี 8.14 จงสร้างคลาสสาหรับรายผลเป็ นสตริง ไม่วา่ จะผ่านค่าตวั เลขหรือสตริงเขา้ ไปใน
เมธอดจะแสดงรายงานผลเป็ นสตริงท้งั หมดโดยคลาสน้ีจะตอ้ งอิมพลีเมนต์อินเทอร์เฟส บวกเลข
ทศนิยม และคลาสการต่อสตริง และออกแบบส่วนการติดตอ่ ผใู้ ชเ้ ป็นสวงิ
คลาสไดอะแกรม
ภาพที่ 8.26 แสดงคลาสไดอะแกรมของตวั อยา่ งท่ี 8.14
297
หลงั จากน้นั ออกแบบส่วนการติดต่อดงั น้ี
ภาพที่ 8.27 แสดงการออกแบบส่วนติดต่อของตวั อยา่ งที่ 8.14
โปรแกรมส่วนการคานวณ
----------------------------------------------------------------------------------------------------------------------
ส่วนป่ ุม +
private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
double x=Double.parseDouble(jTextField1.getText());
double y=Double.parseDouble(jTextField2.getText());
double result=casio.plus(x, y);
jTextField3.setText(casio.report(result));
}
--------------------------------------------------------------------------------------------------------------------
ป่ มุ ต่อสตริง
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
String result=casio.plus(jTextField1.getText(), jTextField2.getText());
jTextField3.setText(String.valueOf(casio.report(result)));
}
--------------------------------------------------------------------------------------------------------------------
ป่ ุมปิ ด
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
298
System.exit(0);
}
--------------------------------------------------------------------------------------------------------------------
ส่วนท้าย
private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton5;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JTextField jTextField1;
private javax.swing.JTextField jTextField2;
private javax.swing.JTextField jTextField3;
--------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั ภาพ
ภาพที่ 8.28 แสดงตวั อยา่ งผลการรันของตวั อยา่ งท่ี 8.14
299
แอบสแทรกคลาส
แอบสแทรกคลาสเป็ นคลาสท่ีออกแบบมาตามแนวคิดคล้ายกันกับอินเทอร์เฟส ใน
ดา้ นหน้าที่ของเมธอดเพื่อให้มีความยืดหยุน่ มากที่สุด โดยการสร้างคลาสชนิดน้ีจะไม่มีการเขียน
ส่วนโคด้ เอาไวเ้ พียงแต่ระบุเมธอดหนา้ ท่ี ค่าท่ีคืน และพารามิเตอร์เท่าน้นั ผทู้ ่ีสืบทอดคุณสมบตั ิไป
ใชง้ านจะตอ้ งเขียนส่วนคาส่ังเองเช่นเดียวกนั กบั อินเทอร์เฟส แต่ขอ้ เสียคือไม่สามารถท่ีจะสืบทอด
ไดห้ ลาย ๆ คลาส เพราะเป็นไปตามกฏการสืบทอดคลาสซ่ึงเป็นสิ่งท่ีแตกต่างกนั กบั อินเทอร์เฟส
การออกแบบภายในคลาสตอ้ งมีเมธอดที่เป็ น Abstract method อยเู่ สมออยา่ งนอ้ ย 1
เมธอด โดยเมธอดน้ีจะตอ้ งไม่มีการเขียนส่วนคาส่ังเอาไว้ ซ่ึงคลาสที่สืบทอดไปจะตอ้ งไปเขียน
คาสั่งอีกคร้ัง โดยใช้การโอเวอร์ไรด์เมธอดน้นั ๆ ใหม่ให้มีส่วนคาส่ังใช้งาน ลกั ษณะของคลาส
ไดอะแกรมและส่วนโครงโปรแกรมดงั น้ี
ภาพท่ี 8.29 แสดงคลาสไดอะแกรมแนวคิดของแอบสแทรกคลาส
โครงโปรแกรม
abstract class abstractClass {
abstract public void methodA();
300
abstract public void methodB();
…
}
class extendtoImplementClass extends abstractClass{
public void methodA(){
//เขียนส่วนคาส่ัง
}
public void methodB(){
//เขียนส่วนคาส่ัง
}
…
}
ตัวอย่างท่ี 8.15 จงออกแบบอินเทอร์เฟสในตวั อยา่ งที่ 8.5 ให้เป็ นส่วนของแอบสแทรกคลาสแลว้ ให้
สามารถคานวณ x=90.5 และ y=23.7 และแสดงผล
คลาสไดอะแกรม
ภาพท่ี 8.30 แสดงคลาสไดอะแกรมของตวั อยา่ งที่ 8.15
301
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
abstract public class abstractCalculator {
abstract public double plus(double number1,double number2);
abstract public double minus(double number1,double number2);
abstract double multiply(double number1,double number2);
abstract double divide(double number1,double number2);
}
----------------------------------------------------------------------------------------------------------------------
public class extendAbstractCal extends abstractCalculator{
public double plus(double number1, double number2) {
return number1+number2;
}
public double minus(double number1, double number2) {
return number1-number2;
}
double multiply(double number1, double number2) {
return number1*number2;
}
public double divide(double number1, double number2) {
return number1/number2;
}
}
----------------------------------------------------------------------------------------------------------------------
public class mainAppAstract {
private static extendAbstractCal casio = new extendAbstractCal();
private static double x=90.50;
private static double y=23.70;
public static void main(String args[]){
System.out.println("x+y="+casio.plus(x, y));
302
System.out.println("x-y="+casio.minus(x, y));
System.out.println("x*y="+casio.multiply(x, y));
System.out.println("x/y="+casio.divide(x, y));
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
x+y=114.2
x-y=66.8
x*y=2144.85
x/y=3.818565400843882
สรุป
อินเทอร์เฟส หมายถึง ส่วนการสร้างส่วนการติดต่อของเมธอดให้ใชง้ านโดยไม่ระบุส่วน
คาสั่ง และสนบั สนุนการทาเป็ นการอิมพลีเมนต์แบบหลายอินเทอร์เฟสร่วมกนั ด้วย การใช้งาน
อินเทอร์เฟสอาจอิมพลีเมนต์เพียงอินเทอร์เฟสเดียวหรือหลาย ๆ อินเทอร์เฟส หรือรวมกบั การใช้
งานส่วนการสืบทอดคุณสมบตั ิ การทาเป็ นโอเวอร์โหลด โอเวอร์ไรด์ก็ได้ สาหรับแอบสแทรก
คลาสเป็ นอีกแนวคิดของคลาสท่ีใชแ้ นวคิดคลา้ ยอินเทอร์เฟสโดยไม่ระบุคาสั่งเพียงแต่บอกส่วน
ต่างๆ ที่เกี่ยวขอ้ งท้งั ส่วนการคืนคา่ และพารามิเตอร์
303
แบบฝึ กหดั ท้ายบท
1. จงบอกความหมายของอินเทอร์เฟส และเปรียบเทียบข้อแตกต่างระหว่าง extends
implements และ abstract class
2. จงเขียนสัญลักษณ์ของอินเทอร์เฟส อินเฮอริทแทน พร้อมท้ังบอกข้อแตกต่างของ
การใชง้ าน
3. จงออกแบบอินเทอร์เฟสของการเปิ ดโทรทัศน์และการควบคุมรีโมท โดยใช้รีโมท
พร้อมท้งั เขียนโครงโปรแกรมท้งั ส่วนอินเทอร์เฟสและส่วนการอิมพลีเมนต์
4. จงเขียนโปรแกรมควบคุมการข้ึนลงลิฟต์อย่างง่าย โดยออกแบบส่วนท่ีสาคัญด้วย
อินเทอร์เฟส
5. จงเขียนโปรแกรมประมวลผลคาอย่างง่าย โดยมีเมธอดการเพิ่มขอ้ ความ การจดั ขอ้ ความ
การแทรกภาพ และการทาส่วนหวั ส่วนทา้ ยของแฟ้ ม
6. การอิมพลีเมนตห์ ลาย ๆ อินเทอร์เฟสมีขอ้ ดีและขอ้ เสียอยา่ งไร
7. ท่านสามารถเขียนโปรแกรมเชิงวตั ถุใหร้ ถยนตบ์ ินไดห้ รือไม่ เพราะเหตุใด
8. การใชง้ านสวงิ น้นั สามารถนาเอาอินเทอร์เฟสเขา้ มาใชง้ านร่วมดว้ ยหรือไมเ่ พราะเหตุใด
9. จงเขียนระบบการจดั การการบรรจุน้าลงขวด โดยโปรแกรมน้ีสามารถนาไปใชก้ บั ขวดชนิด
ใด ๆ กไ็ ด้
10. จงออกแบบและเขียนโปรแกรมจบั เวลาการเขา้ เส้นชยั ของมา้ แข่ง
11. จงบอกความหมายของอินเทอร์เฟสและระบุความจาเป็นท่ีตอ้ งใชอ้ ินเทอร์เฟส
12. ใหอ้ อกแบบอินเทอร์เฟสของการคานวณเงินเดือนของพนกั งานให้สามารถนาไปใชง้ านได้
ทุกหน่วยงาน
13. ท่านคิดวา่ อินเทอร์เฟสมีขอ้ เสียอยา่ งไร
14. การใชง้ านอินเทอร์เฟสร่วมกบั การรับทอดมีขอ้ ดีและขอ้ เสียอยา่ งไร
15. อินเทอร์เฟส แอบสแทรกคลาส ทางานร่วมกนั ไดห้ รือไม่เพราะเหตุใด
304
เอกสารอ้างองิ
กิตติ ภกั ดีวฒั นกุล. (2543 ก). JAVA ฉบบั พนื้ ฐาน. กรุงเทพฯ: ไทยเจริญการพมิ พ.์
_________. (2543 ข). JAVA ฉบบั โปรแกรมเมอร์. กรุงเทพฯ: ไทยเจริญการพมิ พ.์
กิตติ ภกั ดีวฒั นะกุล และ ศิริวรรณ อมั พรดนยั . (2544). Oject-Oriented ฉบับพนื้ ฐาน. กรุงเทพฯ:
KTP Comp&Consult.
กิตติพงษ์ กลมกล่อม. (2552). การวเิ คราะห์และออกแบบระบบเชิงวัตถุด้วย UML. กรุเทพฯ: เคทีพี
แอนด์ คอนซลั ท.์
ธีรวฒั น์ ประกอบผล. (2552). คู่มือการเขียนโปรแกรมภาษา Java. กรุงเทพฯ: ซคั เซส มีเดีย.
_________. (2553). คู่มือการเขียนโปรแกรมภาษา Java. กรุงเทพฯ: ซิมพลิฟลาย.
พนิดา พานิชกลุ . (2548). Object-Oriented ฉบบั พนื้ ฐาน. กรุงเทพฯ: เคทีพี แอนด์ คอนซลั ท.์
_________. (2554). การเขียนโปรแกรมคอมพิวเตอร์เบื้องต้นด้วยภาษาจาวา. พิมพ์คร้ังที่ 5.
กรุงเทพฯ: เคทีพี แอนด์ คอนซลั ท.์
สมโภชน์ ช่ืนเอ่ียม. (2553). วทิ ยาการคอมพวิ เตอร์เบอื้ งต้น. กรุงเทพฯ: ซีเอด็ ยเู คชนั .
Brett Spell. (2000). Professional Java Programming. USA: Wrox Press Ltd. Arden House, 1102
Warwick Road, Acocks Green, Birmingham, B27 6BH, UK.
Bruce Eckel. (2000). Thinking in Java. 2nd . USA: Prentice Hall PTR Prentice-Hall.
Cay Horstmann. (2002). Object-Oriented Design & Patterns. USA: John Wiley & Sons.
David Etheridge. (2009). Java:The Fundamentals of Objects and Classes-An Introduction to
Java Programming. Ventus Publishing Aps. [Online]. Available:
http://www.BookBoon.com
Simol Kendal. (2009). Object Orientted Programming using Java. Ventus Publishing Aps.
[Online]. Available: http://www.BookBoon.com
wikipedia. (2007). “Object-oriented programming”. [Online] Available:
http://en.wikipedia.org/wiki/Object-oriented_programming.
Y. Daniel Liang. (2007). Introduction to Java Programming. USA: Pearson Prentice Hall
Pearson Education, Inc.
บทที่ 9
ภาวะพหุสัณฐาน
เมื่อมีความรู้เร่ืองการสืบทอด อินเทอร์เฟส การโอเวอร์โหลด โอเวอร์ไรด์ แล้วสามารถ
นามาสร้างส่ิงท่ีมีประสิทธิภาพและยืดหยุ่นในเชิงแนวคิดแบบวตั ถุให้มีขีดความสามารถในการ
จดั การโปรแกรมมากข้ึน ทาใหผ้ ใู้ ชไ้ ดใ้ ชง้ านในส่ิงท่ีตนเองตอ้ งการมากข้ึน หากมีการเปล่ียนแปลง
เกิดข้ึนก็ไม่กระทบต่อผูใ้ ช้ และการเขียนโปรแกรมที่ไดเ้ ขียนไวแ้ ลว้ พหุสัณฐาน (Polymorphism)
ทาใหก้ ารเรียกใชง้ านเพยี งคาสงั่ เดียวแตส่ ามารถทาไดห้ ลายหนา้ ที่ตรงตามความตอ้ งการ ในบทน้ีจะ
นาเสนอแนวคิดของพหุสัณฐาน การสร้างการอฟั เคส (Up cast) ดาวน์เคส (Down cast) ที่ช่วย
สาหรับการสร้างพหุสัณฐาน และการพฒั นาโปรแกรมแบบพหุสณั ฐานในรูปแบบตา่ ง ๆ
ความหมายและแนวคดิ ของพหุสัณฐาน
พหุสณั ฐานเป็นคุณลกั ษณะท่ีช่วยขยายขีดความสามารถของการเขียนโปรแกรมเชิงวตั ถุให้
ทางานไดอ้ ยา่ งยดื หยนุ่ มากข้ึน ในชีวิตประจาวนั ของคนเราก็มีลกั ษณะการทางานเป็ นส่วนของพหุ
สณั ฐานเช่นกนั ยกตวั อยา่ ง เช่น นกั คอมพิวเตอร์กล่าวถึงเปิ ดการบูตเครื่องโนต้ บุก๊ ซ่ึงเป็ นการทาให้
เครื่องคอมพิวเตอร์โน้ตบุ๊กจนกระทง่ั สามารถรับคาส่ังและทางานได้ ไม่วา่ จะเป็ นเครื่องโนต้ บุ๊ก
ย่ีห้อใด รุ่นใด ก็จะทาหน้าท่ีทางานไดเ้ ช่นกนั ดว้ ยคาส่ังเพียงคาส่ังเดียวคือคาว่า บูตโน้ตบุ๊ก หรือ
นกั เคมีอาจบอกวา่ การผสมสารต่อไปน้ีตอ้ งอาศยั H2O ซ่ึงสารที่เป็ น H2O น้นั อาจจะอยใู่ นรูปน้าแขง็
น้า หรือไอน้า ซ่ึงทุกรูปแบบต่างใชส้ มการดงั กล่าวได้ นอกจากน้นั ตวั อยา่ งที่ง่ายท่ีสุด เช่น หากครู
แจกกระดาษเปล่าให้นกั เรียน แลว้ ส่ังให้วาดรูปส่งครู จะพบวา่ คาส่ังเพียงคาสั่งเดียวกนั น้ีครูจะได้
รูปภาพที่ไม่ซ้ากนั จากนักเรียนท้งั ห้อง เป็ นตน้ พหุสัณฐานเป็ นความจาเป็ นพ้ืนฐานที่จะขยายขีด
ความสามารถของการเขียนโปรแกรมเชิงวตั ถุ ท่ีรองลงมาจากการจดั การโครงสร้างขอ้ มูลพ้ืนฐาน
และการสืบทอด ไดม้ ีผใู้ หค้ วามหมายของพหุสณั ฐานไวด้ งั น้ี
พนิดา พานิชกุล (2548, หน้า 125) กล่าวว่า การที่วตั ถุหรือคลาสมากกว่าหน่ึงคลาส
สามารถตอบสนองตอ่ เมจเซสเดียวกนั ไดโ้ ดยแสดงพฤติกรรมที่แตกต่างกนั แต่ตอ้ งอาศยั กลไกของ
การสืบทอดเขา้ มาช่วย
306
กิตติ ภกั ดีวฒั นกุล และ ศิริวรรณ อมั พรดนยั (2544, หนา้ 126) กล่าววา่ พหุสัณฐานคือการ
ที่วตั ถุแต่ละวตั ถุสามารถตอบสนองต่อเมสเซจที่ส่งมายงั วตั ถุน้นั ไดด้ ว้ ยตนเอง จะเห็นไดช้ ดั เจนใน
ลกั ษณะของการสืบทอด ซ่ึงแต่ละคลาสยอ่ ยจะสืบทอดลกั ษณะมาจากคลาสแม่ โดยท่ีแต่ละคลาส
ยอ่ ยจะมีเมธอดที่ตอบสนองตอ่ เมจเซสเป็นของตนเอง
จ า ก แ น ว คิ ด เ บ้ื อ ง ต้น ใ น ชี วิ ต ป ร ะ จ า ว ัน แ ล ะ ก า ร ใ ห้ ค า จ า กัด ค ว า ม ที่ น า เ ส น อ ไ ป แ ล้ ว
กล่าวได้ว่า พหุสัณฐาน คือ การที่วตั ถุสามารถตอบสนองต่อการเรียกใช้เมธอดเดียวกัน ใน
สถานการณ์ที่เหมาะสมแตกต่างกนั โดยอาศยั คุณสมบตั ิของการสืบทอด การโอเวอร์ไรดเ์ มธอด เขา้
ช่วยในการจดั การคาสงั่ ตา่ ง ๆ
ตัวอย่างที่ 9.1 จงยกตวั อยา่ งการเรียกใชค้ าสั่งแบบพอ้ งรูปกบั สถานการณ์ในชีวติ ประจาวนั อยา่ งนอ้ ย
สามเหตุการณ์
แนวคดิ เหตุการณ์
เหตกุ ารณ์ที่ 1 มีคนสามคนกาลงั ตกอยใู่ นอนั ตราย คนแรกกาลงั หอ้ ยอยขู่ อบหนา้ ต่างตึกสูง
คนท่ีสองโดนงูกดั ท่ีขอ้ เทา้ คนที่สามกินยาพิษเขา้ ไปโดยไม่รู้ตวั และเม่ือรู้ตวั วา่ ตวั เองกินยาพิษ คน
ท้งั สามต่างตะโกนดว้ ยคาวา่ ช่วยดว้ ย
เหตุการณ์ ท่ี 2 ชายสามคนเดินเขา้ ไปในร้านขายน้าปั่น แลว้ พูดว่าเอาน้าผลไมห้ วาน ๆ
เยน็ ๆ มาหน่ึงแกว้
เหตุการณ์ที่ 3 ในการแข่งขนั การเจาะระบบของบรรดาแฮกเกอร์ท้งั หลาย กรรมการส่ังให้
ดว้ ยคาสงั่ วา่ แฮกเซิร์ฟเวอร์ของบริษทั ซนั ไมโครซิสเตม็
คาอธิบาย จากตวั อยา่ งท่ียกมากล่าวจะพบวา่ ท้งั สามเหตุการณ์จะถูกสั่งการณ์ดว้ ยคาสั่งเดียว
แต่จะได้ผลลพั ธ์และวิธีการท่ีกระทาแตกต่างกนั ไปตามสิ่งที่ควรจะเป็ นตามแต่บุคคล เวลา และ
สถานท่ี แตจ่ ะไดร้ ับผลตามท่ีตนตอ้ งการได้ เป็นตน้
แนวคดิ พหุสัณฐานต่อการเขยี นโปรแกรม
คลาสทุกคลาสจะสืบทอดคุณสมบตั ิมาจากคลาสท่ีช่ือวา่ Object เสมอ โดยปกติแลว้ จะมี
เมธอดและแอตทริบิวตท์ ่ีมีคุณสมบตั ิประจาของ Object มาใหเ้ สมอ ใหพ้ จิ ารณาภาพต่อไปน้ี
307
ภาพที่ 9.1 แสดงตวั อยา่ งแนวคิดการสืบทอดเพื่อสร้างพหุสณั ฐาน
จากภาพดงั กล่าวจะพบว่าคลาสท่ีเป็ นคลาสแม่ คือ Shape แต่ความจริงแลว้ จะมีคลาส
Object เป็น Super Class ของทุก ๆ คลาสเสมอ ดงั น้นั คุณสมบตั ิบางประการยอ่ มจะถูกสืบทอดและ
หนา้ ท่ีบางอยา่ งจะถูกเรียกใชเ้ หมือนกนั และหากพิจารณาท่ีคลาส Square ซ่ึงเป็ นคลาสระดบั ล่างสุด
สืบทอดคุณสมบตั ิจาก Rectangle Shape และ Object ตามลาดบั ซ่ึงตามแนวคิดเชิงพหุสัณฐานแลว้
เมธอดที่มีใชใ้ น Shape ก็ควรจะเรียกใชไ้ ดใ้ น Square หรือเพ่ิมคลาส Triangle ข้ึนมาอีกคลาสแลว้
สืบทอดคุณสมบตั ิจาก Shape เมธอดของ Triangle ก็ควรจะเรียกใช้เช่นเดียวกนั กบั Shape หรือ
Square เป็นตน้
พหุสัณฐานในความหมายของการเขียนโปรแกรมเชิงวตั ถุน้นั คือ ความสามารถของการ
อา้ งถึงหรือสร้างวตั ถุท่ีเกิดจากคลาสต่าง ๆ ในตอนรันโปรแกรมโดยไม่ทราบล่วงหนา้ ว่าเป็ นของ
คลาสใดในตอนคอมไพล์ เพื่อให้สามารถใชง้ านเมธอด ตวั แปร หรือค่าต่าง ๆ ในชื่อเดียวกนั ซ่ึงจะ
ถูกสร้างเพื่อเรียกใชต้ อนรันโปรแกรม ซ่ึงแบ่งความสามารถที่เก่ียวขอ้ งกบั การใชง้ านคลาสใน 3
แนวทางหลกั ดงั น้ี
1. ความสามารถในด้านของการสับเปลย่ี น (substitutability)
ความสามารถดงั กล่าวน้ีเป็ นความสามารถทางด้านการเขียนรหสั ของโปรแกรม
ใหส้ งั เกตภาพตอ่ ไปน้ี
308
ภาพที่ 9.2 แสดงตวั อยา่ งการสืบทอดของรถยนต์
จากคลาสไดอะแกรมน้ีมีเมธอด drive() ในคลาสแม่และคลาสลูกที่สืบทอดมายอ่ มมีเมธอด
ดงั กล่าวดว้ ยเสมอ ในท่ีที่จะพบอนุมานไดว้ า่ คาสั่งหรือโคด้ ในเมธอด drive() ของคลาสแม่จะตอ้ ง
สามารถทางานได้ ในคลาสลูกไดท้ ุก ๆ คลาสที่สืบทอดมาดว้ ยเช่นกนั ซ่ึงความสามารถดงั กล่าวน้ี
คือการสามารถแลกเปลี่ยนสับเปล่ียนดงั กล่าว
การเรียกใชง้ านเรียกไดด้ งั น้ี
motorCar car;
car=new Toyota();
car.drive();
car=new Honda();
car.drive();
car=new Isuzu();
car.drive();
จากรหสั โปรแกรมดา้ นบนจะพบวา่ การใชง้ านเมธอดดว้ ยคาสั่ง car.drive(); จะใชง้ านไดผ้ ล
กบั รถทุก ๆ ยหี่ อ้ เป็นตน้ หรือหากพิจารณาในลกั ษณะของความเป็ นจริงไม่วา่ จะเป็ นยหี่ ้อใดหากส่ัง
ให้ขบั รถก็จะทาการเคล่ือนท่ีเป็ นตน้ เพราะเหตุที่วา่ Toyota, Honda และ Isuzu ต่างก็คือ motorCar
ที่ใชค้ วามสมั พนั ธ์แบบ has-a ทาใหก้ ารใชง้ านจะตอ้ งเหมือนกนั เป็นตน้
309
ตัวอย่างที่ 9.2 จงออกแบบคลาสสาหรับการขายอาหารจานด่วนสามชนิด มีขา้ วไข่เจียว ขา้ วผดั
ขา้ วหนา้ เป็ด ตามแนวทางของการแลกเปลี่ยนรหสั โปรแกรมกนั ได้
ภาพที่ 9.3 แสดงการสืบทอดเพ่อื พหุสัณฐานของอาหารจานด่วน
2. ความสามารถในด้านของการขยายขดี ความสามารถ (Extensibility)
ความสามารถในการขยายขีดความสามารถเป็นการใชง้ านส่วนที่เพ่ิมเติมเขา้ ให้กบั
กลุ่มคลาสที่มีอยู่แล้ว โดยไม่มีผลกระทบต่อคลาสท่ีมีอยู่ขณะท่ีคลาสที่เขา้ มาเพิ่มก็ยงั
สามารถสั่งไดด้ ว้ ยคาส่ังแบบเดิมและเรียกใชเ้ มธอดแบบเก่าที่เคยเรียกมา ให้พิจารณาภาพ
ตอ่ ไปน้ี
ภาพที่ 9.4 แสดงเพม่ิ เติมคลาสเขา้ มาเพือ่ เรียกใชง้ านตามแนวทางพหุสณั ฐาน
310
จากภาพดงั กล่าวน้ีเม่ือเพม่ิ คลาส Ford เขา้ การเรียกใชง้ านเมธอด dirve() กย็ งั คงเหมือนเดิม
motorCar car;
car=new Toyota();
car.drive();
car=new Honda();
car.drive();
car=new Isuzu();
car.drive();
car=new For();
car.drive();
การใชง้ านยงั คงเรียกใช้งาน car.drive(); กบั คลาสใหม่ท่ีเพ่ิมเขา้ มาขณะเดียวกนั ก็ยงั เรียก
แบบเดิมท้งั หมดโดยไม่มีผลกระทบ โดยท่ีรหัสโปรแกรมเก่าที่ยงั อย่กู ็ยงั ทางานไดเ้ หมือนเดิมกบั
คลาสเดิมหรือแมก้ ระทง่ั คลาสใหม่ท่ีเพ่ิมเขา้ มาก็สามารถทางานไดเ้ ช่นกนั ซ่ึงคุณสมบตั ิดงั กล่าวน้ี
เรียกวา่ การขยายขีดความสามารถ
ตัวอย่างที่ 9.3 จากตวั อยา่ งท่ี 9.2 หากขา้ วไข่เจียวมีสองแบบ และเพิ่มเมนูก๋วยเตี๋ยวเขา้ ไปอีก จง
ออกแบบใหม้ ีความยดื หยนุ่ ตามหลกั การของการขยายขีดความสามารถ
คลาสไดอะแกรม
ภาพที่ 9.5 แสดงคลาสไดอะแกรมของตวั อยา่ งท่ี 9.3
311
3. ความสามารถในการสืบทอดคุณสมบตั ิ (inheritance and interface)
ความสามารถของการใชง้ าน การสืบทอดคุณสมบตั ิและอินเทอร์เฟส จะช่วยให้มีการสร้าง
วตั ถุเพือ่ ใชง้ านเม่ือรันโปรแกรม โดยท่ีจะระบุแบบไม่ยดึ ติดกบั คลาสใดคลาสหน่ึงได้ เช่นกรณีของ
ภาพท้งั สองของคลาส motorCar หากเจา้ นายบอกวา่ ใหเ้ อารถยนต์ มาหน่ึงคนั ใหข้ บั ไปส่ง คนขบั
รถยนตไ์ ม่ทราบก่อนวา่ จะตอ้ งขบั คนั ไหนไป จะทราบกต็ ่อเมื่อไปถึงโรงรถและเห็นตวั รถที่เหลืออยู่
เท่าน้นั หลงั จากน้นั ก็ขบั ออกมา ไม่วา่ รถดงั กล่าวจะเป็ นยี่ห้ออะไรก็ตาม ก็เป็ นรถยนตท์ ้งั สิ้นลว้ น
สามารถขับได้ท้ังน้ัน ในกรณีดังกล่าวน้ีต้องสร้างเป็ นคลาสแล้วสืบทอดหรือไม่ก็สร้างเป็ น
อินเทอร์เฟสสาหรับนามาอิมพลีเมนตเ์ องในตอนจะทางานจริง ตวั อยา่ งรหสั โปรแกรม เช่น
motorCar car;
if(…)
car=new Ford()
else
car=new Toyota();
car.drive();
จากแนวทางของรหสั โปรแกรมดงั กล่าวน้นั ตอ้ งการใช้งานรถยนตเ์ พียงคนั เดียว แต่ตอ้ ง
เลือกสร้างวตั ถุโดยพิจารณาจากคาส่ัง if เง่ือนไขตามท่ีตอ้ งการเมื่อรันโปรแกรม หลงั จากน้นั จึงจะ
เรียกใชด้ ว้ ยเมธอดเดียวกนั
คุณสมบตั ิและแนวคิดของพหุสัณฐานจะเกิดข้ึนได้ ตอ้ งเกี่ยวขอ้ งกบั การสืบทอดในรูปแบบ
ของอินเฮอริทแทนและอินเทอร์เฟส นอกจากน้นั การใชค้ าส่ังสาหรับการบงั คบั ให้คลาสระดบั ของ
คลาสยอ่ ยกลายเป็ นคลาสแม่ (Upacast) หรือการบงั คบั ใหค้ ลาสแม่กลายเป็ นคลาสยอ่ ย (Downcast)
จึงจะสามารถทาใหไ้ ดค้ ุณสมบตั ิดงั กล่าวได้
เครื่องมือสาหรับสร้างการใช้งานพหุสัณฐาน
การเขียนโปรแกรมให้มีรูปแบบพหุสัณฐานไดน้ ้นั มีหลายรูปแบบ ซ่ึงการท่ีจะเขียนแต่ละ
แบบไดน้ ้ีจะตอ้ งมีความรู้เกี่ยวกบั การสืบทอด การสร้างอินเทอร์เฟส การสร้างเมธอดโอเวอร์โหลด
ทาการโอเวอร์ไรดเ์ มธอดได้ นอกจากน้นั ส่ิงที่สาคญั ที่ตอ้ งมีเพมิ่ เขา้ ไปอีกคือ
- การเคสติง้ ไทป์ ไดแ้ ก่อฟั เคสและดาวน์เคสคลาสได้ (Upcast and Downcast)
- การเรียนรู้การสร้างตวั แปรแบบยดึ ติดและแบบพลวตั ได้ (static and dynamic binding)
312
อฟั เคสตงิ้ (Upcasting)
อฟั เคสติ้ง คือ การที่สามารถแปลงชนิดของวตั ถุจากคลาสแม่ไปเป็ นวตั ถุของคลาสยอ่ ยที่
สืบทอดกนั อยหู่ รือการแปลงจากวตั ถุของคลาสยอ่ ยให้กลายเป็ นคลาสแม่ได้ การดาเนินการเช่นน้ี
เพยี งเพื่อสร้างความยดื หยนุ่ ใหก้ บั โปรแกรมไดใ้ ชง้ านตามท่ีผใู้ ชเ้ ลือกหรือตอ้ งการให้มากท่ีสุด โดย
แนวคิดน้ีมีการแปลงอยู่ 2 แบบคือ อฟั เคสติ้ง และ ดาวน์เคสติ้ง แสดงดงั รูปตอ่ ไปน้ี
อฟั เคสตงิ้
ภาพที่ 9.6 แสดงภาพการอฟั เคสติ้ง อย่างน้ ี เรี ยกว่า
อฟั เคสติง้ สามารถทาได้ 3 รูปแบบดงั น้ี
1. ประกาศตวั แปรเป็นตวั แม่แลว้ สร้างวตั ถุเป็นตวั คลาสยอ่ ย เช่น
SuperClass Obj;
Obj = new SubClass();
การทาเช่นน้ีจะทาให้คลาส SubClass() กลายวตั ถุของ SuperClass
การอฟั เคสโดยตรง แตส่ ามารถอฟั เคสไดด้ งั น้ีไดอ้ ีกคือ
2. ประกาศตวั แปรและสร้างวตั ถุข้ึนมาท้งั คูห่ ลงั จากน้นั จบั มาเท่ากนั เช่น
SuperClass Obj=new SubperClass();
SubClass Obj1 = new SubClass();
Obj = Obj1;
หรือ การทาเช่นน้ี
3. การบงั คบั ชนิดโดยตรง เช่น
313
SuperClass Obj;
SubClass Obj1 = new SubClass();
Obj = (SuperClass)Obj1;
ตวั อยา่ งต่อไปน้ีแสดงการอฟั เคสติ้ง เพือ่ นาไปสู่การประยุกตใ์ ชง้ านต่อไป
ตัวอย่างท่ี 9.4 กาหนดใหม้ ีคลาสแมค่ ือคลาส นาฬิกา และตวั คลาสยอ่ ยคือคลาสนาฬิกาโรเลก็ ซ์
หลงั จากน้นั ใหท้ าการอฟั เคสโรเลก็ ซ์ใหก้ ลายเป็นวตั ถุของคลาสนาฬิกา พร้อมท้งั แสดงยห่ี อ้ ของ
ตวั เองออกมา พร้อมบอกวา่ นาฬิกาไดเ้ ดินแลว้
คลาสไดอะแกรม
ภาพท่ี 9.7 แสดงคลาสไดอะแกรมของตวั อยา่ งที่ 9.4
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class Clock {
public void showName(){
System.out.println("I am a Clock.");
}
public void move(){
314
System.out.println("Tick Tock.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class Rolex extends Clock{
public void move() {
System.out.println("Rolex Tick Tock.");
}
public void showName() {
System.out.println("I am a Rolex from Clock.");
}
}
----------------------------------------------------------------------------------------------------------------------
ตัวอย่างน้ีแสดงทง้ั สามรูปแบบของการอัฟเคส
Main แบบที่ 1
----------------------------------------------------------------------------------------------------------------------
public class mainApp {
public static void main(String args[]){
Clock c;
c=new Rolex();
c.showName();
c.move();
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน จะแสดงดงั น้ี
I am a Rolex from Clock.
Rolex Tick Tock.
315
Main แบบที่ 2
----------------------------------------------------------------------------------------------------------------------
public class mainApp {
public static void main(String args[]){
Clock c=new Clock();
Rolex r=new Rolex();
c=r;
c.showName();
c.move();
}
}
---------------------------------------------------------------------------------------------------------------------
Main แบบท่ี 3
----------------------------------------------------------------------------------------------------------------------
public class mainApp {
public static void main(String args[]){
Clock c;
Rolex r=new Rolex();
c=(Clock)r;
c.showName();
c.move();
}
}
----------------------------------------------------------------------------------------------------------------------
ตัวอย่างท่ี 9.5 จากตวั อยา่ งที่ 9.3 จงเขียนโปรแกรมแสดงการอฟั เคสให้ RiceAndOmeletA เป็นวตั ถุ
ชนิด fastFood โดยกาหนดใหม้ ีส่วนโปรแกรมเรียกใชง้ าน
คลาสไดอะแกรม นามาจากภาพท่ี 9.3
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
316
public class fastFood {
public void serv(){
System.out.println("Fast Food is served.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class RiceAndOmelet extends fastFood{
public void serv() {
System.out.println("RiceAndOmelet is served.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class RiceAndOmeletA extends RiceAndOmelet{
public void serv() {
System.out.println("RiceAndOmeletA is served.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class mainfastFoodApp {
public static void main(String args[]){
fastFood f;
f=new RiceAndOmeletA();
f.serv();
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
RiceAndOmeletA is served.
317
คาอธิบาย ขอ้ สังเกตจากตวั อยา่ งท้งั สองพบว่าการสร้างการอฟั เคสน้นั สามารถทาไดถ้ า้ คลาสยอ่ ย
ที่สืบทอดคุณสมบตั ิมาจากคลาสแม่ สามารถบงั คบั ใหต้ วั คลาสยอ่ ยเป็นตวั แม่ได้
ข้อดีของการอฟั เคสคอื
1. รหสั โปรแกรมง่ายในการที่อ่านหรือเขียน
2. รูปแบบการติดตอ่ จะกาหนดเฉพาะรายละเอียดของคลาส
3. ถา้ หากมีการเปลี่ยนรูปแบบ จะไม่มีผลกระทบต่อผใู้ ช้ และทาการเปลี่ยนรูปไม่ยงุ่ ยาก
ข้อเสีย
หากมีการบงั คบั คลาสแม่เป็ น คลาสลูก จะดาเนินการค่อนขา้ งยงุ่ ยาก หรือถา้ ดาวน์เคส
(down cast) จะยงุ่ ยาก
การดาวน์เคส
การดาวน์เคส คือ การทาให้คลาสแม่เป็นคลาสยอ่ ยท่ีสืบทอดคุณสมบตั ิแนวคิด แสดงดงั ภาพ
ตอ่ ไปน้ี
ดาวน์เคส
ภาพที่ 9.8 แสดงภาพคลาสไดอะแกรมของการดาวน์เคส
โครงโปรแกรม
1. ประกาศตวั แปรเป็นตวั แม่แลว้ สร้างวตั ถุเป็นตวั คลาสยอ่ ย เช่น
SubClass sc;
SuperClass sp= new SubClass();
318
sc=(SubClass) sp;
โดยทั่วไปจะสร้างการดาวน์เคสได้น้ันต้องสร้างวตั ถุชนิดเดียวกันกับท่ีจะดาวน์เคส
เสียก่อนหากสร้างเป็นวตั ถุชนิดของคลาสแม่แลว้ ดาวนเ์ คสโดยตรงจะไมส่ ามารถทาได้
เช่น SuperClass a=new SuperClass();
SubClass b=(SubClass) a;
กรณีเช่นน้ีไม่สามารถทาได้ เพราะคุณสมบตั ิหรือค่าบางค่าอาจเกิดปัญหาไดใ้ นทางปฏิบตั ิ
จึงไม่สามารถทาไดซ้ ่ึงภาษาจาวาก็เช่นเดียวกนั ดงั น้นั การดาวน์เคสตอ้ งสร้างส่วนดงั โครงโปรแกรม
กล่าวแลว้
ตวั อย่างที่ 9.6 จากตวั อยา่ งของคลาสนาฬิกาของตวั อยา่ งที่ 9.3 จงเขียนโปรแกรมโดยใชว้ ธิ ีในการ
ดาวน์เคส
คลาสไดอะแกรมและคลาสประกอบอ่ืนเหมือนเดิมแต่ส่วนของการเรียกใชง้ านในคลาส
หลกั จะเปล่ียนไป ดงั น้ี
โปรแกรม :
public class mainApp {
public static void main(String args[]){
Rolex r;
Clock c=new Rolex();
r=(Rolex)c;
r.showName();
r.move();
}
}
ผลการรัน แสดงดงั น้ี
I am a Rolex from Clock.
Rolex Tick Tock.
319
ตวั อย่างท่ี 9.7 จากตวั อยา่ งที่ 9.5 จงเขียนโดยใชว้ ธิ ีดาวนเ์ คส
คลาสไดอะแกรมและคลาสประกอบอื่นเหมือนเดิมแต่ส่วนของการเรียกใช้งานในคลาส
หลกั จะเปลี่ยนไป ดงั น้ี
โปรแกรม :
public class mainfastFoodApp {
public static void main(String args[]){
fastFood f;
f=new RiceAndOmeletA();
RiceAndOmeletA rao=(RiceAndOmeletA)f;
rao.serv();
}
}
ผลการรัน แสดงดงั น้ี
RiceAndOmeletA is served.
การดาวน์เคสน้นั ไม่สามารถทาไดห้ ลายกรณีเหมือนการอฟั เคส ซ่ึงมีความยุง่ ยากมากกวา่
ในการเขียนโปรแกรม และสิ่งน้ีก็กลายเป็ นขอ้ เสียของการทาพหุสัณฐานได้ เพราะว่าหากมีการ
ดาวน์เคสที่ไม่เหมาะสมโปรแกรมอาจเกิดปัญหาของการเกิดขอ้ ผดิ พลาดข้ึนมาไดน้ นั่ เอง
การกาหนดตวั แปรแบบยดึ ติดและแบบพลวตั
การกาหนดตวั แปรแบบยึดติด เป็ น การประกาศตวั แปรหรือแอตทริบิวต์ท่ีเรารู้แน่ชดั ว่า
วตั ถุท่ีจะสร้างข้ึนน้นั สามารถประกาศไดแ้ ละสร้างวตั ถุข้ึนไดท้ นั ที ซ่ึงการประกาศลกั ษณะน้ีตอน
คอมไพลโ์ ปรแกรมสามารถจบั ความผดิ พลาดได้ หรือจดั ไดใ้ นตอนคอมไพลโ์ ปรแกรม
การกาหนดตวั แปรแบบพลวตั คือการประกาศตวั แปรแบบยดื หยนุ่ ตอนคอมไพล์โปรแกรม
ไม่สามารถรู้ไดล้ ่วงหนา้ วา่ ผใู้ ชง้ านจะใชว้ ตั ถุใด จะรู้ก็ต่อเมื่อตอนรันโปรแกรมแลว้ เท่าน้นั ซ่ึงเป็ น
ตอนท่ีสร้างวตั ถุจริงเพือ่ ทางาน
ในชีวิตประจาวนั น้ันสามารถเทียบกับการประกาศตวั แปรท้งั สองแบบได้ เช่น หากมี
ร้านอาหารท่ีขายอาหารอยา่ งเดียว เช่น ก๋วยเต๋ียวเป็ ดอยา่ งเดียว เจา้ ของร้านอาจตกั ก๋วยเต๋ียวใส่ถว้ ย
เอาไวไ้ ดเ้ ลย ลูกคา้ คนใดเขา้ มาในร้านก็ตอ้ งกินก๋วยเต๋ียวเป็ดอยา่ งแน่นอนเพราะไมม่ ีอาหารชนิดอ่ืน
320
ให้เลือก กรณีอยา่ งน้ีอาจเปรียบไดก้ บั การประกาศตวั แปรแบบยึดติด แต่หากมีอีกร้านขายอาหาร
จานเดียวเช่นกนั ซ่ึงขายท้งั ผดั กระเพรา ขา้ วผดั ก๋วยเตี๋ยว และอ่ืน ๆ อีก ในกรณีเช่นน้ีไม่อาจจะตกั
ใส่จานเอาไวร้ อลูกคา้ ได้ จะทราบวา่ จะตอ้ งทาอะไรก็ต่อเม่ือลูกคา้ สั่งแลว้ เท่าน้นั กรณีเช่นน้ีอาจ
เทียบไดก้ บั การประกาศตวั แปรแบบพลวตั ได้ กล่าวคือเจา้ ของร้านเพียงแต่เตรียมจานสาหรับใส่
อาหารเท่าน้นั แต่ยงั ไม่นาอาหารชนิดใดลงไปในจาน เทียบกบั การประกาศเพียงระบุชื่อและชนิด
ของตวั แปรไวเ้ ท่าน้นั ยงั ไมม่ ีการสร้างวตั ถุใชง้ านจริง เป็นตน้
ใหพ้ จิ ารณาการประกาศดงั ตอ่ ไปน้ี
Class A{
//implememts
}
Class B{
//implements
}
public static void main(String args[]){
String s; //static binding
A x; //static binding
B y; //static binding
…
if(s.compareTo(“1”)==0){
y=new B(); //dynamic binding
}
else
{
x=new A(); //dynamic binding
}
}
จากตวั อยา่ งดา้ นบนน้ี การประกาศ A x; B y; เป็นการระบุแบบยดึ ติดที่ไม่อาจหลีกเลี่ยงการ
รับรู้จากตอนคอมไพล์ไดเ้ ลย ซ่ึงการประกาศลกั ษณะที่เป็ นการยึดติดน้ีส่วนมากแลว้ จะใชก้ บั การ
ประกาศตวั แปรที่เป็ นตวั แปรพ้ืนฐานต่าง ๆ เช่น int, float , String และอ่ืน ๆ ท่ีเป็ น แอบสแตรก
ดาตา้ ไทป์ (Abstract data type) เป็ นตน้ แต่การประกาศในลกั ษณะท่ีสองคือแบบพลวตั น้ี ตอน
321
คอมไพล์โปรแกรมไม่สามารถทราบไดว้ ่าเป็ นวตั ถุใดของคลาสใดกนั แน่ท่ีจะถูกสร้าง เช่นกรณี
ดา้ นบนน้ี คอมไพล์เลอร์ไม่สามารถระบุได้วา่ จะสร้างวตั ถุใดกนั แน่ระหวา่ ง x=new A() หรือ
y=new B() จะทราบไดก้ ็ต่อเมื่อรันโปรแกรมแลว้ ผใู้ ชส้ ่งพารามิเตอร์เขา้ มา ถา้ หากเป็ น “1” y=new
B() จะทางานเป็ นตน้ การประกาศตวั แปรในลกั ษณะน้ีในการใชง้ านโครงสร้างขอ้ มูลแบบซบั ซ้อน
ของภาษาจาวาไดเ้ ตรียมชนิดของตวั แปรท่ีรองรับการประกาศเช่นน้ีดว้ ย คือ กลุ่มของตวั แปรท่ีเป็ น
ArrayList, List, Vector เป็นตน้
ตวั อย่างที่ 9.8 จงเขียนโปรแกรมใหส้ มบูรณ์โดยพมิ พว์ า่ คลาสใดท่ีถูกทางานเม่ือผา่ นพารามิเตอร์ใน
รูปแบบต่าง ๆ กนั
คลาสไดอะแกรม
ภาพที่ 9.9 แสดงคลาสไดอะแกรมของตวั อยา่ งท่ี 9.8
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class A {
public A(){
System.out.println("I am A.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class B {
322
public B(){
System.out.println("I am B.");
}
}
----------------------------------------------------------------------------------------------------------------------
import java.io.*;
public class mainDyanmicApp {
public static void main(String args[])throws IOException{
String s; //static binding
A x; //static binding
B y; //static binding
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(reader);
System.out.println("Input String :");
s=stdin.readLine();
if(s.compareTo("1")==0)
{
y=new B(); //dynamic binding
}
else
{
x=new A(); //dynamic binding
}
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
Input String : 1
I am B.
323
หากป้ อนสตริงอื่น ๆ
Input String :xxx
I am A.
แนวคิดอีกแนวทางของการสร้างตวั แปรแบบพลวตั คือ การท่ีตวั แปรชนิดเดียวสามารถ
ดาเนินการไดก้ บั วตั ถุหลาย ๆ ประเภท เช่น ถา้ มีคลาส A, B, C, D โดยที่คลาสท้งั หมดสืบทอดมา
จากคลาส E สามารถประกาศตวั แปรที่เป็นตวั แม่แลว้ เกบ็ ตวั คลาสยอ่ ยที่สืบทอดมาไดท้ ้งั หมด
Class E{
//implement
}
Class A extends E{
//implement
}
Class B extends E{
//implement
}
Class C extends E{
//implement
}
public static void main(String args[]){
E Obj[]=new E[4];
…
Obj[0]=new A();
Obj[1]=new B();
Obj[2]=new C();
Obj[3]=new D();
}
จากโครงโปรแกรมดา้ นบนน้ีพบวา่ Obj[0] เป็ น วตั ถุของคลาส A Obj[1] เป็ น วตั ถุของ
คลาส B และ Obj[2] เป็นวตั ถุของคลาส C และ Obj[3] เป็น วตั ถุของคลาส D ตามลาดบั ในกรณีจะ
324
พบวา่ มีความยดื หยนุ่ และเป็นพลวตั มาก เพราะอาร์เรยข์ อง E สามารถสร้างการทางานท่ีเกบ็ วตั ถุของ
คลาสตา่ งคลาสกนั ได้ เป็นตน้
ตัวอย่างท่ี 9.9 จากแนวคิดดา้ นบนจงเขียนโปรแกรมใหส้ มบูรณ์
คลาสไดอะแกรม
ภาพที่ 9.10 แสดงคลาสไดอะแกรมของตวั อยา่ งท่ี 9.8
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class E {
}
----------------------------------------------------------------------------------------------------------------------
public class A extends E{
325
public A(){
System.out.println("I am A.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class B extends E{
public B(){
System.out.println("I am B.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class C extends E{
public C(){
System.out.println("I am C.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class D extends E{
public D(){
System.out.println("I am D.");
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
I am A.
I am B.
I am C.
I am D.
326
การสร้างความเป็ นพลวตั ของวตั ถุน้ันสามารถประกาศเป็ น Object ซ่ึงเป็ นคลาสแม่
ของทุกคลาส การใชง้ านจะประกาศคลาส Object ไวแ้ ลว้ สามารถที่จะนาเอาคลาสใด ๆ ก็ไดเ้ ขา้ มา
เกบ็ ไว้
Object obj1;
Object obj2;
Object obj3;
หลงั จากน้นั สามารถท่ีจะสร้างวตั ถุใด ๆ ก็ได้ เช่น
obj1=new A();
obj2=new B();
obj3=new C();
ดงั น้นั ใหพ้ ิจารณาการใชง้ านจากตวั อยา่ งตอ่ ไปน้ี
ตวั อย่างที่ 9.10 จงเขียนโปรแกรมโดยประกาศตวั แปรตวั แปรหลกั เป็น Object
คลาสไดอะแกรม
ภาพที่ 9.11 แสดงคลาสไดอะแกรมของตวั อยา่ งที่ 9.9
327
คลาส A B C D และ E จะเหมือนเดิมทุกประการ แต่ส่วนการสร้างวตั ถุในส่วนของ
โปรแกรมหลกั จะแตกต่างกนั ดงั น้ี
โปรแกรม :
public class mainDyanmicApp {
public static void main(String args[]){
Object Obj[]=new Object[4];
Obj[0]=new A();
Obj[1]=new B();
Obj[2]=new C();
Obj[3]=new D();
}
}
ผลการรันจะได้เหมือนเดิม แต่หากเป็ นการนาไปใช้งานจริงเมื่อจะอ้างถึงจะต้องทา
การอฟั เคสติ้ง เพื่อใหไ้ ดด้ งั ที่ตอ้ งการ เช่น
A a=(A)Obj[0];
B b=(B)Obj[1];
C c=(C)Obj[2];
D d=(D)Obj[3];
การดาเนินการโดยใช้ Object น้ีขอ้ สาคญั ผูเ้ ขียนโปรแกรมจะตอ้ งทราบวา่ กาลงั จะจดั การ
กบั วตั ถุใดในขณะน้นั สาหรับหลกั การแบบน้ีภาษาจาวาไดเ้ ตรียมโครงสร้างขอ้ มูลสาหรับเก็บวตั ถุ
เช่น ArrayList, Vector เป็ นตน้ การใชง้ านจะตอ้ งประกาศตวั แปรเหล่าน้ีเอาไวก้ ่อนแลว้ ใช้ เมธอด
add() เพ่อื สร้างวตั ถุ และนามาใชง้ านดว้ ยการเรียกใชเ้ มธอด elementAt() ตวั อยา่ งการใชง้ าน ดงั น้ี
Vector obj;
หลงั จากน้นั สามารถท่ีจะสร้างวตั ถุใด ๆ ก็ไดเ้ ช่น
Obj.add(new A());
Obj.add(new B());
Obj.add(new C());
การนามาใชง้ านจะตอ้ งเรียกใชเ้ มธอด elementAt() เช่น
A a= obj.elementAt(0);
B b= obj.elementAt(1);
328
C c= obj.elementAt(2);
ใหพ้ จิ ารณาตวั อยา่ งต่อไปน้ี
ตวั อย่างที่ 9.11 จงเขียนโปรแกรมสร้างคลาสผลไม้ Banana Grape และ Durian โดยมีเมธอดสาหรับ
แสดงช่ือตนเอง โดยใช้ java.util.Vector
คลาสไดอะแกรม
ภาพที่ 9.12 แสดงคลาสไดอะแกรมของตวั อยา่ งที่ 9.10
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class Banana {
public String showName(){
return "I am Banana.";
}
}
----------------------------------------------------------------------------------------------------------------------
public class Grape {
public String showName(){
return "I am Grape.";
}
}
----------------------------------------------------------------------------------------------------------------------
329
public class Durian {
public String showName(){
return "I am Durian.";
}
}
----------------------------------------------------------------------------------------------------------------------
public class mainFruitApp {
public static void main(String args[]){
Vector Obj=new Vector();
Obj.add(new Banana());
Obj.add(new Grape());
Obj.add(new Durian());
System.out.println(((Banana)Obj.elementAt(0)).showName());
System.out.println(((Grape)Obj.elementAt(1)).showName());
System.out.println(((Durian)Obj.elementAt(2)).showName());
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
I am Banana.
I am Grape.
I am Durian.
การใชง้ านการประกาศ Object และ Vector หรือ ArrayList จะมีความยืดหยุน่ มากสาหรับ
การประกาศแบบพลวตั แต่จาเป็ นตอ้ งรู้ว่ากาลงั จะจดั การวตั ถุชนิดใดและตอ้ งใช้วิธีการดาวน์เคส
เพื่อนามาใชง้ าน ซ่ึงอาจจะเกิดความผดิ พลาดข้ึนได้
330
การสร้างพหุสัณฐานโดยโอเวอร์โหลดดงิ้
การเขียนโปรแกรมแบบการสร้างพหุสัณฐาน สามารถทาไดจ้ ากการทาโอเวอร์โหลดดิ้ง
การสืบทอด อินเทอร์เฟส และแอบสแทรกคลาส ต่อไปน้ีจะแสดงวิธีการสร้าง คลาสไดอะแกรม
โครงโปรแกรม และตวั อยา่ งโปรแกรม
การสร้างพหุสัณฐานโดยใช้โอเวอร์โหลดดิง้
การสร้างพหุสัณฐานจากคุณสมบตั ิการโอเวอร์โหลดดิ้ง น้ันสามารถทาได้ง่ายท่ีสุด
เน่ืองจากผเู้ ขียนโปรแกรมไม่ตอ้ งใชค้ ุณสมบตั ิการสืบทอดที่ยงุ่ ยากใด ๆ เลย วิธีการคือสร้างคลาสท่ี
ตอ้ งการท้งั หมดข้ึนมาแลว้ กาหนดใหค้ ลาสหลกั น้นั สร้างเมธอดสาหรับการใชค้ ลาสท่ีตอ้ งการทีละ
เมธอด หลกั การสร้างคลาสเป็นดงั รูปตอ่ ไปน้ี
ภาพที่ 9.13 แสดงแนวคิดการสร้างพหุสัณฐานดว้ ยโอเวอร์โหลดดิ้ง
โครงโปรแกรม
---------------------------------------------------------------------------------------------------------
class classA{
public void doSomething(){
//implement
331
}
}
-----------------------------------------------------------------------------------------------------------
class classB{
public void doSomething(){
//implement
}
}
-----------------------------------------------------------------------------------------------------------
class classC{
public void doSomething(){
//implement
}
}
-----------------------------------------------------------------------------------------------------------
class OverloadingClass {
public void executCommand(classA a) {a.doSomething()}
public void executCommand(classB a) {a.doSomething()}
public void executCommand(classC a) {a.doSomething()}
}
-----------------------------------------------------------------------------------------------------------
ในส่วนของโปรแกรมหลกั จะตอ้ งประกาศดงั น้ี
OverloadingClass oc = new OverloadingClass();
classA a=new classA();
classB b=new classB();
classC c=new classC();
oc.executeCommand(a);
oc.executeCommand(b);
oc.executeCommand(c);
332
จากส่วนของโปรแกรมหลกั ดงั กล่าวจะทาใหเ้ มธอด doSomething ของแต่ละคลาสทางาน
โดยการเรียกใชง้ านของ oc.executeCommand() เป็นตน้
ตัวอย่างท่ี 9.12 จากตวั อยา่ งของ classA, classB, และ classC ดงั กล่าวมีหนา้ ที่สาหรับแสดงชื่อของ
ตนเอง จงสร้างพหุสัณฐานสาหรับการเรียกใชง้ านแสดงชื่อดงั กล่าว
คลาสไดอะแกรม
ภาพที่ 9.14 แสดงคลาสไดอะแกรมของตวั อยา่ งท่ี 9.12
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class classA {
public void doSomething(){
System.out.println("I am the object of classA.");
}
}
----------------------------------------------------------------------------------------------------------------------
333
public class classB {
public void doSomething(){
System.out.println("I am the object of classB.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class classC {
public void doSomething(){
System.out.println("I am the object of classC.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class mainOverloadExam {
public static void main(String args[]){
OverloadingClass oc = new OverloadingClass();
classA a=new classA();
classB b=new classB();
classC c=new classC();
oc.executeCommand(a);
oc.executeCommand(b);
oc.executeCommand(c);
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
I am the object of classA.
I am the object of classB.
334
I am the object of classC.
ตัวอย่างท่ี 9.13 จากตวั อยา่ งที่ 9.11 คลาสผลไม้ Banana Grape และ Durian โดยมีเมธอดสาหรับ
แสดงช่ือตนเอง ให้สร้างเมธอดสาหรับแสดงบอกราคาผลไม้ หลงั จากน้นั เขียนโปรแกรมให้ผูใ้ ช้
เลือกผลไมด้ งั กล่าว แลว้ แสดงชื่อและราคา โดยใชห้ ลกั การพหุสัณฐานดว้ ยการโอเวอร์โหลดดิ้ง
คลาสไดอะแกรม
ภาพท่ี 9.15 แสดงคลาสไดอะแกรมของตวั อยา่ งที่ 9.13
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class Banana {
public String showName(){
return "I am Banana.";
}
335
public int showPrice(){
return 20;
}
}
----------------------------------------------------------------------------------------------------------------------
public class Grape {
public String showName(){
return "I am Grape.";
}
public int showPrice(){
return 120;
}
}
----------------------------------------------------------------------------------------------------------------------
public class Durian {
public String showName(){
return "I am Durian.";
}
public int showPrice(){
return 60;
}
}
----------------------------------------------------------------------------------------------------------------------
public class FruitOverload {
public void chosenFruit(Banana b){
System.out.println(b.showName());
System.out.println("Price:"+b.showPrice());
}
public void chosenFruit(Grape g){
System.out.println(g.showName());
336
System.out.println("Price:"+g.showPrice());
}
public void chosenFruit(Durian d){
System.out.println(d.showName());
System.out.println("Price:"+d.showPrice());
}
}
----------------------------------------------------------------------------------------------------------------------
import java.io.*;
public class FruitShop {
public static void main(String args[])throws IOException{
InputStreamReader reader = new InputStreamReader(System.in);
BufferedReader stdin = new BufferedReader(reader);
FruitOverload f = new FruitOverload();
String choice="";
System.out.println("Input choice 1=Banana, 2=Grape, and 3=Durian :");
choice=stdin.readLine();
if(choice.compareTo("1")==0){
Banana bn=new Banana();
f.chosenFruit(bn);
}else
if(choice.compareTo("2")==0){
Grape gr=new Grape();
f.chosenFruit(gr);
}else
if(choice.compareTo("3")==0){
Durian dr=new Durian();
f.chosenFruit(dr);
}else
System.out.println("Incorrect choice.");
337
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
Input choice 1=Banana, 2=Grape, and 3=Durian :1
I am Banana.
Price:20
Input choice 1=Banana, 2=Grape, and 3=Durian :
2
I am Grape.
Price:120
Input choice 1=Banana, 2=Grape, and 3=Durian :
3
I am Durian.
Price:60
การทาแบบน้ีมีขอ้ เสียคือหากมีการเพ่ิมคลาสใหม่เขา้ มาจะตอ้ งปรับการเขียนคลาสท่ีเป็ น
คลาสสาหรับการโอเวอร์โหลดเช่น คลาสผลไมด้ งั กล่าว หากมีการเพิ่มผลไมช้ นิดใหม่เขา้ มา ผเู้ ขียน
โปรแกรมจะตอ้ งสร้างเมธอดสาหรับการโอเวอร์โหลดของคลาส FruitOverlaod ดว้ ย แต่หากใช้
หลกั การที่จะกล่าวต่อไป ไมจ่ าเป็นตอ้ งปรับคลาสอื่นเพียงแตเ่ พม่ิ เขา้ มาไดท้ นั ที
การสร้างพหุสัณฐานด้วยการสืบทอด
การสร้างดว้ ยการสืบทอดน้ี จะคล้ายกบั หลกั การท่ีได้กล่าวมาแลว้ กล่าวคือ สร้างคลาส
ท้งั หมดในรูปแบบของการสืบทอด โดยมีคลาสแม่ เป็ นคลาสหลกั ที่จะใหค้ ลาสที่จะรันโปรแกรม
เรียกใช้ ซ่ึงการสร้างวตั ถุน้นั จะเกิดข้ึนตอนรันโปรแกรมและใช้วิธีการอฟั เคสติ้งดงั ท่ีกล่าวมาแลว้
ในตวั อยา่ งที่ 9.4 และ 9.5 เป็นตน้ แนวทางของคลาสไดอะแกรมและโครงโปรแกรมเป็นดงั น้ี
338
ภาพที่ 9.16 แสดงแนวคิดการสร้างพหุสณั ฐานดว้ ยการสืบทอด
โครงโปรแกรม :
----------------------------------------------------------------------------------------------------------------------
Class SuperClass{
Public void methodX(){
//implement
}
}
----------------------------------------------------------------------------------------------------------------------
class SubClassA{
public void methodX(){
//implement
}
}
----------------------------------------------------------------------------------------------------------------------
class SubClassB{
public void methodX(){
//implement
}
339
}
----------------------------------------------------------------------------------------------------------------------
class SubClassC{
public void methodX(){
//implement
}
}
----------------------------------------------------------------------------------------------------------------------
class PolymorphismClient{
…
public static void main(String args[]){
SuperClass sp;
…
sp=new SubClassA();
..
sp=new SubClassB();
…
sp=new SubClassC();
}
}
----------------------------------------------------------------------------------------------------------------------
ตัวอย่างท่ี 9.14 จากแนวคิดการสืบทอด จงเขียนโปรแกรมให้เมธอด methodX ท่ีเป็ นเมธอดท่ีมี
ความสามารถของซุปเปอร์ฮีโร่ ไดแ้ ก่ Bat Man, Super Man, Spider Man โดยกาหนดให้ เป็ น
อาร์เรยข์ อง SuperClass
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class SuperClass {
public void methodX(){
System.out.println("I am the X men.");
340
}
}
----------------------------------------------------------------------------------------------------------------------
public class SubClassA extends SuperClass{
public void methodX(){
System.out.println("I am Bat man Yark!.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class SubClassB extends SuperClass{
public void methodX(){
System.out.println("I am Super man Wiew!.");
}
}
----------------------------------------------------------------------------------------------------------------------
public void methodX(){
System.out.println("I am Spider man Ting-Neud!.");
}
}
----------------------------------------------------------------------------------------------------------------------
public class PolymorphismClient {
public static void main(String args[]){
SuperClass sp[]=new SuperClass[4];
sp[0]=new SuperClass();
sp[1]=new SubClassA();
sp[2]=new SubClassB();
sp[3]=new SubClassC();
sp[0].methodX();
sp[1].methodX();
sp[2].methodX();
341
sp[3].methodX();
}
}
----------------------------------------------------------------------------------------------------------------------
ผลการรัน แสดงดงั น้ี
I am the X men.
I am Bat man Yark!.
I am Super man Wiew!.
I am Spider man Ting-Neud!.
ตัวอย่างที่ 9.15 กาหนดใหร้ ้านขายอาหารมีเมนูใหล้ ูกคา้ เลือกดงั น้ี
อาหาร เครื่องด่ืม ผลไม้
ขา้ วไข่เจียว 25 บาท น้าเปล่า 10 บาท สัปปะรด 15 บาท
ก๋วยเตี๋ยว 20 บาท น้าส้ม 20 บาท แอปเปิ้ ล 20 บาท
สปาเกตตี 40 บาท โคก้ 25 บาท มะมว่ ง 15 บาท
กาหนดใหล้ ูกคา้ ที่เขา้ มาในร้านเลือกสินคา้ ได้ 1 ชนิดเทา่ น้นั จงเขียนโปรแกรมใหล้ ูกคา้ เลือก และ
รายงานผล
คลาสไดอะแกรม แสดงดงั ภาพที่ 9.17
โปรแกรม :
----------------------------------------------------------------------------------------------------------------------
public class fastFood {
public String showName(){
return "Not implemented yet.";
}
public int showPrice(){
return 0;
}
}
----------------------------------------------------------------------------------------------------------------------
342
343
public class RiceAndOmelet extends fastFood{
public String showName(){
return "ขา้ วไข่เจียว.";
}
public int showPrice(){
return 25;
}
}
----------------------------------------------------------------------------------------------------------------------
public class Noodle extends fastFood{
public String showName(){
return "ก๋วยเตี๋ยว.";
}
public int showPrice(){
return 20;
}
}
----------------------------------------------------------------------------------------------------------------------
public class Spaghetti extends fastFood{
public String showName(){
return "สปาร์เกต็ ต้ี.";
}
public int showPrice(){
return 40;
}
----------------------------------------------------------------------------------------------------------------------
public class Drinking {
public String showName(){
return "Not implemented yet.";
}
344
public int showPrice(){
return 0;
}
}
----------------------------------------------------------------------------------------------------------------------
public class PureWater extends Drinking{
public String showName(){
return "น้าเปล่า.";
}
public int showPrice(){
return 10;
}
}
----------------------------------------------------------------------------------------------------------------------
public class OrangeJuice extends Drinking{
public String showName(){
return "น้าส้ม.";
}
public int showPrice(){
return 20;
}
}
----------------------------------------------------------------------------------------------------------------------
public class CokaCola extends Drinking{
public String showName(){
return "โคก้ .";
}
public int showPrice(){
return 25;
}