บทที่ 5 Objects และ Classes 146เร่มิ ตน กับ Java } //swapping contents of given objects private static void swap(Values pointA, Values pointB) { Values temp = new Values(); temp = pointA; //copy pointA to temp pointA = pointB; //copy pointB to pointA pointB = temp; //copy temp to pointB }}เรากาํ หนดใหก ารสลบั คา ของ object ทงั้ สองเกิดข้ึนภายใน swap() ซึง่ เราคดิ วา นา จะทาํ ได 100% แตหลงั จากท่ี run โปรแกรมดู เรากลบั ไดผลลพั ธด งั น้ี(10, 20)(30, 50)(10, 20)(30, 50)ซึง่ บอกใหเ รารวู า swap() ของเราใชไมไ ด เราตองเปล่ยี นแปลง code ของ swap() ใหมเ พือ่ ใหก ารสลับเกดิ ข้นึ จรงิ และหลังจากท่เี ราเปลีย่ น code ใหเปนprivate static void swap(Values pointA, Values pointB) { Values temp = new Values(); temp.val1 = pointA.val1; temp.val2 = pointA.val2; pointA.val1 = pointB.val1; pointA.val2 = pointB.val2; pointB.val1 = temp.val1; pointB.val2 = temp.val2;}ผลลัพธท เ่ี ราไดคอื(10, 20)(30, 50)(30, 50)(10, 20)ซึ่งแสดงถงึ การสลับคา ที่ไดผ ลจริง สาเหตทุ ี่ swap() ตัวแรกของเราทาํ งานไมไ ด ก็เน่ืองจากวา การเปลย่ี นแปลงคา ของ object เกิดข้ึนจาก copy ของ object ท้งั สองที่มาจาก parameter ไมใชตวั objectจรงิ ๆ ดงั นัน้ การเปลยี่ นแปลงท่ีเกิดขึ้นจึงเกิดขึ้นภายในตัว swap() ไมมผี ลกระทบใด ๆ กบั objectภายนอกเลย เราตอ งทาํ การเปล่ยี นคาใหกับสมาชิกท่ีอยูใน object นัน้ โดยตรงดังเชน ท่ี swap() ตวั ทส่ี องไดแ สดงไวเราไดพ ูดถึง class Student ที่เราสรา งคางไวโดยเราไดสาํ รวจ การสราง method ตา ง ๆ รวมไปถงึ การสงคาเขาสู method ตอนนีเ้ ราจะมาดูถงึ รายละเอียดของ method ตาง ๆ ท่มี อี ยใู น class Student รวมไปถงึโปรแกรมทเี่ รยี กใช object ทเี่ กิดจาก class Studentกอนทเี่ ราจะพดู ถึง method ทม่ี อี ยใู น class Student เรามาดตู วั โปรแกรมท่เี รียกใช method เหลา นี้ดู//TestStudent.java ภาควิชาคอมพิวเตอรธ รุ กจิ วทิ ยาลยั ฟารอ สี เทอรน
บทที่ 5 Objects และ Classes 147เรมิ่ ตน กับ Javaclass TestStudent { public static void main(String[] args) { //create two student objects with given info. Student stu1 = new Student(\"19757\", \"Jim\", \"Jones\", \"02/10/1962\"); Student stu2 = new Student(\"20135\", \"Ray\", \"Smith\", \"12/09/1977\"); //display each student's info. stu1.display(); stu2.display(); //display total number of students System.out.println(\"Total number of objects created: \" + stu1.getCount()); //access field in class via object String date = stu1.dateOfBirth; System.out.println(\"Date of birth of stu1 is \" + date); }}เราไดสราง object stu1 และ stu2 จาก class Student ดว ยขอ มลู ดงั ที่เหน็Student stu1 = new Student(\"19757\", \"Jim\", \"Jones\", \"02/10/1962\")Student stu2 = new Student(\"20135\", \"Ray\", \"Smith\", \"12/09/1977\")หลังจากนัน้ เรากเ็ รียกใช method display() ในการแสดงผลขอมูลของ object ทัง้ สองตัว โดยทีเ่ ราไดออกแบบ method display() ของเราใหมกี ารเรียกใช method อื่น ๆ ทมี่ ีอยูใน class Student ดังน้ีpublic void display() { System.out.print(getId() + \" \"); System.out.print(getFirstName() + \" \"); System.out.print(getLastName() + \" \"); System.out.println(\"Age: \" + getAge()); return ;}ผูอ า นจะสังเกตไดวา เราเรยี ก method getId() getFirstName() getLastName() และ methodgetAge() ภายในประโยคของ System.out.println(…) ซ่ึง method เหลาน้จี ะสงคาของ field ตาง ๆ ที่ไดถ กู กําหนดไวใ หก บั ประโยคในการแสดงขอมูลไปยงั หนา จอหลงั จากท่ีขอ มูลของ object ทงั้ สองตวั ไดถ กู แสดงไปยังหนาจอแลว เรากเ็ รียกประโยคSystem.out.println(\"Total number of objects created: \" + stu1.getCount());String date = stu1.dateOfBirth;System.out.println(\"Date of birth of stu1 is \" + date);สาํ หรบั การแสดงจํานวนของ object ท่ไี ดถ ูกสรางขนึ้ ทั้งหมด และวนั เดอื น ป เกดิ ของ object ทช่ี ื่อ stu1ไปยังหนา จอ และผลลพั ธของการ run ทไ่ี ดค อื19757 Jim Jones Age: 4120135 Ray Smith Age: 26Total number of objects created: 2Date of birth of stu1 is 02/10/1962 ภาควิชาคอมพิวเตอรธุรกิจ วิทยาลยั ฟารอสี เทอรน
บทที่ 5 Objects และ Classes 148เรมิ่ ตน กับ Javaผูอานตองกาํ หนดใหก ารเรียก method ที่มอี ยูใ น class ผานทาง object ท่ีไดส รา งขึ้น ดวยการใช . (dot)ตามดวยชอ่ื ของ method ทีต่ อ งการเรยี กใช เชนstu1.display();เชน เดียวกนั กบั การเรียกใช data member เรากต็ องขนึ้ ตน ดว ยชื่อของ object ตามดวย . (dot) ตามดว ยตวั แปรทตี่ องการใช เชนstu1.dateOfBirth;เน่อื งจากวา เราไมไดก าํ หนดนโยบายการเขา หา ตวั แปร หรอื method ท่มี อี ยใู น class ดังนั้นการเขาหาจงึไมขอ กําหนดใด ๆ เราสามารถทจี่ ะเขาหาขอมูลทกุ ตวั โดยไมม ีขอ จาํ กดั กอนที่เราจะพดู ถงึ นโยบายการเขาหาขอ มูลทอ่ี ยูใน class เราอยากที่จะพูดถึง method getAge() ท่ีมีอยูใ น class Student สักเลก็ นอ ยmethod getAge() ไดถกู ออกแบบใหท าํ การคํานวณหาอายุดวยการหาจากการลบปเ กดิ ออกจากปปจ จบุ ัน ดงั น้นั เราจึงตอ งเรยี กใช method จาก class Calendar ในการคาํ นวณหาปปจ จุบัน ดังนี้public int getAge() { //retrieve a year String year = dateOfBirth.substring(6); //convert it to an int int birthYear = Integer.parseInt(year); //get current year from system's calendar Calendar now = Calendar.getInstance(); int thisYear = now.get(Calendar.YEAR); //return the difference return thisYear - birthYear;}กอนทเี่ ราจะคํานวณหาอายไุ ด เราตองดึงเอา field ท่เี ปน ปเกดิ ทอ่ี ยใู นรูปแบบของ dd/mm/yyyy ออกมากอนดว ยการใช method substring() ที่เราไดพ ูดไวก อ นหนา นี้ เมอื่ ไดแ ลวเราก็เปลีย่ น string ทีม่ ีคาเปนปเกดิ นีใ้ หเ ปน int ดวยการเรยี กใช Integer.parseInt()หลงั จากนน้ั เราก็ดึงเอาปป จจุบนั ออกจากเคร่อื งดวยคาํ สัง่Calendar now = Calendar.getInstance();int thisYear = now.get(Calendar.YEAR);ซ่ึงกอนท่เี ราจะดงึ ปออกไดเ ราตอ งสรา ง instance จาก class Calendar กอ นและเมื่อไดแ ลว เรากใ็ ชmethod get() ในการดึงเอาปป จ จบุ นั ออกมา กระบวนการที่เหลืออยกู ค็ ือการสง สว นตางระหวา งปป จ จุบันกับปเกดิ ออกไปยงั ผทู ีเ่ รยี กใช method นี้ (การดึงเอาคา ของปอ อก ผูอา นตอ งระวงั ในเรือ่ งของปท ่ีใชใ นเครอ่ื ง ณ เวลานัน้ ดวยวา อยูในรูปแบบของ พุทธศักราช หรอื ครสิ ตศักราช Windows ใหม ๆ ยอมใหมีการตง้ั คา ตามตาํ แหนงทตี่ ้งั ของประเทศน้นั ๆ)การสราง class Student ของเรานั้นเราไมไดก าํ หนดนโยบายการเขา หา field หรอื method ตา ง ๆ ของเราอยางไรเลย ผูอา นคงสังเกตเห็นวา ตัวแปรทุกตวั ของเราไมมคี ําใด ๆ นําหนา เลย เชน private publicหรอื แมก ระทั่งคาํ วา protected หวั ขอตอไปจะพดู ถงึ เรอ่ื งของการกําหนดนโยบายการเขา หาตัวแปร และmethod ของ class วาจะมีประโยชนอ ยา งไรในการออกแบบ class (ผอู า นลองตัง้ คาํ ถามใหต วั เองกอ นเร่มิ หัวขอถัดไปวา ถาใสค าํ วา private หนาตวั แปรทุกตัวจะมีผลตอโปรแกรม TestStudent.java อยางไรถาใสหนา method ตา ง ๆ หละ?) ภาควิชาคอมพิวเตอรธรุ กจิ วิทยาลยั ฟารอ สี เทอรน
บทท่ี 5 Objects และ Classes 149เรม่ิ ตนกบั Javaการกาํ หนดนโยบายในการเขา หาสมาชกิ ของ class (attributes)จาก class Circle ของเราทไี่ ดส รา งขนึ้ ในการประกาศตัวแปร radius นัน้ เราไดก าํ หนดใหม คี ําวา privateอยูดา นหนา ของตัวแปร ดงั นี้private double radius;ทาํ ไมเราถึงทาํ เชน น้ี?สาเหตทุ ่เี ราทําเชนนก้ี ็เพือ่ ท่ีจะกําหนดการเขา หาตวั แปรตวั น้ี โดยท่วั ไปแลว ถา เราไมใ สค าํ วา private ไวหนาตวั แปรใด เราก็สามารถทจี่ ะเขา หาตวั แปรตวั นี้ ผานทางโปรแกรมอน่ื ๆ ท่ีเรยี กใช class Circle การกาํ หนดนโยบายของการเขา หานนั้ เราสามารถทาํ ไดสวี่ ิธี คอื1. ไมใ ชค ําใด ๆ นาํ หนาตวั แปร (friendly)2. ใชคาํ วา private นาํ หนา ตวั แปร (not too friendly)3. ใชค าํ วา public นําหนาตวั แปร (friendly)4. ใชค าํ วา protected นาํ หนาตวั แปร (somewhat friendly)ถา เราไมใชคาํ ใด ๆ นาํ หนา ตวั แปรการเขาหาตวั แปรตวั นจี้ ะทําไดเฉพาะ class ทอ่ี ยูภายในพื้นทีเ่ ดยี วกนัเชนภายใน class เดียวกนั หรอื ภายใน package (ดเู รอื่ งการสรางและใช package ทา ยบท) เดยี วกัน ดงัโปรแกรมตวั อยา งที่แสดงใหด นู ้ี//Access.javaclass Dot { //no access control String name; int value; Dot(String s, int v) { name = s; value = v; }}class Access { public static void main(String[] args) { Dot myDot = new Dot(\"I am a dot.\", 10); //access both name and value fields from class Dot System.out.println(\"Name is \" + myDot.name); System.out.println(\"Value is \" + myDot.value); }}เมือ่ เรา run ดูผลลพั ธท ี่ไดค ือName is I am a dot.Value is 10โปรแกรม Access.java สามารถทจี่ ะเขา หา field ท้งั สองที่เราสรา งข้นึ ใน class Dot ของเราผา นทางobject ช่อื myDot (หมายความวา ใคร ๆ ก็เขา หาตัวแปรของเราไดถ า เขารูวา เรามตี วั แปรอะไรบา ง –อันตราย?)ทีน้เี ราลองนาํ เอาคาํ วา private ไปใสไวห นา ตวั แปรทง้ั สองของเรา ดงั น้ีprivate String name; ภาควิชาคอมพิวเตอรธุรกจิ วิทยาลัยฟารอีสเทอรน
บทท่ี 5 Objects และ Classes 150เรมิ่ ตน กับ Javaprivate int value;การ compile โปรแกรมอีกครั้งหนึ่งจะทําใหเกดิ error ดงั นี้Access.java:20: name has private access in Dot System.out.println(\"Name is \" + myDot.name); ^Access.java:21: value has private access in Dot System.out.println(\"Value is \" + myDot.value); ^2 errorsเราไมส ามารถทีจ่ ะอางถงึ ตัวแปรท้งั สองไดเ พราะคาํ วา private เราตอ งเขา หาดวยวธิ อี ื่น เชน เขียนmethod ท่ีสงคา ของตวั แปรทง้ั สองกลับ (โดยเขียนไวใ น class Dot) เหมือนกบั ที่เราไดท าํ ไวใน classCircleเรากาํ หนดใหตวั แปร radius ของ class Circle เปน private data member ดังนน้ั เราจึงตอ งเขยี นmethod ในการเขา หาตัวแปร radius ของเรา ดงั นี้public double getRadius() { return radius;}เพราะฉะนนั้ ถาเราไมตอ งการใหโปรแกรม หรอื ผูใด (object) เขา หาตวั แปรของเรา เราก็นาํ คาํ วา privateไปแปะไวด า นหนา ของตัวแปรน้ัน ๆ ถา สงั เกตใหด ีจะเหน็ วา method changeRadius() ใน class Circle ก็มีคาํ วา private อยูดา นหนาเหมือนกนั ท้งั น้กี ็เพราะวา เราไมต อ งการใหใครเขา หา method ตัวนยี้ กเวนmethod ทีอ่ ยภู ายใน class เดียวกัน การเขา หา method นผี้ านโปรแกรม หรอื object ตัวอน่ื จะทาํ ไมไ ดและ Java compiler จะฟอ งดว ย error ทันทีเราจะกลับมาดคู าํ วา protected ในโอกาสตอ ไป ทงั้ นี้เพราะคาํ ๆ นม้ี ีเงือ่ นไขซบั ซอ นอยูพ อสมควร สําหรบัคําวา public น้ันจะยอมใหท ุกโปรแกรม หรือ object เขาหาตัวแปร หรือ method ไดโ ดยไมม ีเง่ือนไขใดๆ ท้ังส้ินการกําหนดนโยบายการเขาหาตัวแปรหรอื method ทําใหก ารควบคมุ โปรแกรมทําไดดยี ิ่งข้นึ อะไรทผี่ ูใ ชไมควรรูไมค วรเห็น เราก็ซอนสงิ่ เหลานไี้ ว การกระทาํ ในลกั ษณะนเ้ี ราเรยี กวา encapsulation ซงึ่ เปนหนึง่ในขอกําหนดของการออกแบบและเขยี นโปรแกรมในรูปแบบของ OOP ในสวนตวั ของผูเ ขียนแลว ชอบที่จะใช private กบั ตัวแปรทกุ ตวั และ method บางตวั ท่ีไมม ีการเขา หาจากภายนอก เพราะจะทําใหก ารใชตวั แปรมีขอจํากดั สว นทเ่ี ขา หาขอมลู เหลา นข้ี องเราไดเ ปนไดเฉพาะ method ท่เี ราไดก ําหนดไวเทานัน้Constructor อกี ครงั้Constructor มีไวส ําหรบั การกาํ หนดคา เบอ้ื งตนใหก ับตวั แปรท่ีอยใู น class และการเรียกใช constructorนน้ั เราไมต อ งทาํ โดยตรง constructor จะถกู เรยี กโดยอัตโนมตั ผิ า นทางการสรา ง object จาก class ดังที่ไดแ สดงไวใ นโปแกรมทส่ี ราง object จาก class Circle จากประโยคของการสรา งวงกลมทว่ี าCircle red = new Circle(5.0);ขั้นตอนท่เี กิดขนึ้ เม่ือประโยคนถ้ี ูก execute คอืConstructor ของ Circle ถกู เรยี กดว ยคา 5.0 ซ่ึงหมายความวาตัวแปร radius ท่อี ยูใน class Circle จะไดรบั คา ท่กี ําหนดให คอื 5.0 หลงั จากน้ันตาํ แหนง หรือ address ของ object ทถ่ี ูกสรางและกําหนดคาน้ีจะถูกเกบ็ ไวใ น red เพื่อใหเหน็ ภาพชดั ขน้ึ เราจะเพิม่ ประโยคดา นลางน้ีเขากบั constructor ของ classCircleSystem.out.println(\"Constructor activated with parameter value of \" + radius); ภาควิชาคอมพิวเตอรธ ุรกิจ วทิ ยาลยั ฟารอสี เทอรน
บทท่ี 5 Objects และ Classes 151เริม่ ตน กับ Javaเพราะฉะนน้ั constructor ของ class Circle ก็จะเปนCircle(double r) { radius = r; System.out.println(\"Constructor activated with value of \" + radius);}และเราจะลองสราง object สองตัวจาก class Circle ดงั นี้class PassByReference { public static void main(String[] args) { Circle red = new Circle(5.0); Circle blue = new Circle(3.5);}หลังจากท่ี compile และ run ผลลพั ธท ไ่ี ดค อืConstructor activated with value of 5.0Constructor activated with value of 3.5เราจะเห็นวา object สองตวั ถกู สรา งดวย radius ท่ีตางกัน คอื 5.0 และ 3.5 และทงั้ ๆ ทไ่ี มม ปี ระโยคของการแสดงผลใน method main() ใด ๆ เลย เรากลับไดผ ลลพั ธด ังท่เี หน็ ท้ังนก้ี ็เพราะวา constructor ของเราทมี่ ีอยใู น class Circle ไดรับการเรียกใชโดยอตั โนมตั ิเราสามารถทจ่ี ะสรา ง constructor ใหกบั class ไดม ากกวาหนึง่ ตวั ทั้งนี้การกระทาํ ดงั กลา วจะตอ งอยูภายใตเ งอ่ื นไขที่ Java กําหนดไว คือ parameter ทีส่ ง ไปยงั constructor ตองไมม จี าํ นวนทเี่ ทา กนั และถาจํานวนของ parameter เทากัน ชนิดของ parameter ตอ งไมเหมือนกนั (หนังสอื เกือบทกุ เลม เรียกขนั้ ตอนนี้วาการกําหนด signature) ลองดโู ปรแกรมตัวอยาง//TestMean.javaclass Mean { private double x, y, z; //constructor with one value Mean(double value) { x = value; y = 0.0; z = 0.0; } //constructor with two values Mean(double value1, double value2) { x = value1; y = value2; z = 0.0; } //constructor with three values Mean(double value1, double value2, double value3) { x = value1; y = value2; z = value3; } ภาควิชาคอมพิวเตอรธรุ กจิ วทิ ยาลยั ฟารอีสเทอรน
บทท่ี 5 Objects และ Classes 152เริ่มตน กับ Java public double findMean() { return (x + y + z) / 3; }}class Mean ของเรามี constructor อยูส ามตวั โดยทต่ี ัวแรกมี parameter หนึง่ ตวั constructor ตวั ทสี่ องมี parameter สองตวั และ constructor ตัวทส่ี ามมี parameter สามตวั ภายใน class เราไดสรา งmethod findMean() สําหรบั การคํานวณหาคา เฉล่ยี ของตวั แปรท้ังสามของ class และเราไดเขยี นโปรแกรมสําหรบั ตรวจสอบการใช constructor ดังกลาวดงั นี้class TestMean { public static void main(String[] args) { //create objects with diferent parameters Mean m = new Mean(12.0); Mean n = new Mean(10.0, 20.0); Mean p = new Mean(10.0, 20.0, 30.0); System.out.println(\"Mean of m is \" + m.findMean()); System.out.println(\"Mean of n is \" + n.findMean()); System.out.println(\"Mean of p is \" + p.findMean()); }}โปรแกรม TestMean.java ประกาศใช object จาก class Mean สามตัวดว ยจาํ นวนของ parameter ที่ตา งกัน คอื หนง่ึ ตัว สองตวั และสามตัวตามลําดบั หลงั จากทีเ่ ราเรยี ก method findMean() สาํ หรับobject ทัง้ สามตวั แลว ผลลัพธทีเ่ ราไดจ ากการ run คือMean of m is 4.0Mean of n is 10.0Mean of p is 20.0จะเห็นวา Java เลือกใช constructor ไดถ กู ตองตามการออกแบบทีเ่ รากาํ หนดไว ซงึ่ วิธกี ารแบบนเี้ ราเรยี กวา constructor overloading เรามาลองดกู าร overload ของ constructor ทีม่ จี ํานวนของparameter เหมอื นกนั แตตางชนิดกันดู อกี สกั ตวั อยา งหน่งึ//TestMean1.javaclass Mean { private double x, y, z; //constructor with three values Mean(double value1, double value2, double value3 { x = value1; y = value2; z = value3; } //constructor with three values (different type) Mean(double value1, int value2, String value3) { x = value1; y = (double)value2; z = Double.parseDouble(value3); } public double findMean() { return (x + y + z) / 3; }} ภาควิชาคอมพิวเตอรธรุ กจิ วทิ ยาลยั ฟารอีสเทอรน
บทที่ 5 Objects และ Classes 153เรม่ิ ตนกับ Javaclass Mean ของเรากาํ หนดใหม ี constructor สองตัว โดยกาํ หนดใหต ัวแรกรบั parameter ท่ีเปนdouble ทงั้ สามตวั สว น constructor ตัวทส่ี องรับ parameter ทีเ่ ปน double int และ String ตามลาํ ดบัซง่ึ เราไดเ ปล่ยี นคาทไี่ มใ ช double ของทัง้ สอง parameter ใหเ ปน double ภายในตวั constructor เองclass TestMean1 { public static void main(String[] args) { //create objects with diferent parameters Mean p = new Mean(10.0, 20.0, 30.0); Mean q = new Mean(10.0, 20, \"40.0\"); System.out.println(\"Mean of p is \" + p.findMean()); System.out.println(\"Mean of q is \" + q.findMean()); }}โปรแกรม TestMean1.java ประกาศการใช object สองตวั คอื p และ q จาก class Mean ดว ยparameter ตา งกันดังท่ีเหน็ ผลลพั ธทีไ่ ดข องการ run คอืMean of p is 20.0Mean of q is 23.0333333333333332เชน เดยี วกับโปรแกรมกอนหนา นี้ ผลลพั ธท ไ่ี ดแสดงถงึ การเรียกใช constructor ท่ีถูกตองของ Javaยังมีวิธอี ื่นทเ่ี ราสามารถทจ่ี ะ overload constructor ได วิธีน้ีเราจะเรยี ก constructor ตัวอน่ื จากconstructor อกี ตวัการเรียก constructor จาก constructorวิธกี ารเรยี ก constructor จาก constructor ก็ไมย าก เราเพยี งแตกาํ หนดวธิ ีการเรียกใหเหมาะสม ซ่ึงJava ยอมใหมกี ารเรยี ก constructor จาก constructor ผา นทางคาํ วา this ดังตวั อยา งท่ไี ดแ สดง ดงั นี้//TestMean2.javaclass Mean { private double x, y, z; //constructor with one value Mean(double value) { x = value; y = 0.0; z = 0.0; } //constructor with two values Mean(double value1, double value2) { //calling constructor with one argument this(value1); y = value2; } //constructor with three values Mean(double value1, double value2, double value3) { //calling constructor with two arguments this(value1, value2); z = value3; } ภาควิชาคอมพิวเตอรธ รุ กิจ วิทยาลยั ฟารอ สี เทอรน
บทท่ี 5 Objects และ Classes 154เร่มิ ตนกับ Java public double findMean() { return (x + y + z) / 3; }}class TestMean2 { public static void main(String[] args) { //create objects with diferent parameters Mean m = new Mean(12.0); Mean n = new Mean(10.0, 20.0); Mean p = new Mean(10.0, 20.0, 30.0); System.out.println(\"Mean of m is \" + m.findMean()); System.out.println(\"Mean of n is \" + n.findMean()); System.out.println(\"Mean of p is \" + p.findMean()); }}เราไดด ดั แปลงโปรแกรมของการหาคา เฉลย่ี ของเลขสามตัวกอ นหนา นใี้ ห มี constructor ทเี่ รยี กใชconstructor ดงั นี้Mean(double value) { x = value; y = 0.0; z = 0.0;}Mean(double value1, double value2) { //calling constructor with one argument this(value1); y = value2;}Mean(double value1, double value2, double value3) { //calling constructor with two arguments this(value1, value2); z = value3;}constructor ตวั แรกกาํ หนดคา ใหกบั ตัวแปรเชนเดียวกับทไี่ ดทาํ ไวก อนหนา น้ี สวน constructor ตัวทสี่ องและสามเรยี กใช constructor ทม่ี อี ยภู ายใน class Mean ดว ยการเรยี กผา น this() โดยที่ constructor ตัวทีส่ องเรยี ก constructor ตวั แรกดวยคําสง่ั this(value1) เมื่อ Java เหน็ การเรยี กเชน นี้ ก็จะไปหาconstructor ทม่ี อี ยใู น class วา มตี ัวไหนบางท่มี ีเงื่อนไขตามท่ถี ูกเรยี ก ซงึ่ ก็เปน ไปตามน้ันคือ Java ไปเรียก constructor ทีม่ ี parameter เพียงตวั เดยี วมาทําการกาํ หนดคาเบอื้ งตน ใหกับ object ที่ executeconstructor ตวั นี้ คอื x จะมคี า เปน value1 y และ z จะมีคา เปน 0.0 จากการกําหนด หลงั จากนนั้ การกาํ หนดคา ให y เปน value2 ก็ไดถูกกระทําภายใน constructor ตวั ทสี่ องconstructor ตวั ทส่ี ามก็เชน เดยี วกัน การเรยี ก constructor ทม่ี ี parameter 2 ตวั ก็เกิดข้นึ กระบวนการเดิมทไี่ ดกลา วไวกอนหนา นี้กไ็ ดถูกกระทําขน้ึ เมือ่ ทาํ เสรจ็ แลว การกาํ หนดคา ใหกับตัวแปร z จงึ มขี ึ้น(ผลลัพธของโปรแกรม TestMean2.java กเ็ หมอื นกบั ท่เี ราไดก อนหนาน้)ีการเรยี กใช constructor ทีม่ อี ยแู ลว ทาํ ใหก ารเขียน code ที่ซาํ้ ซอนลดลง การเขียนโปรแกรมก็มีประสทิ ธภิ าพมากข้ึน ภาควิชาคอมพิวเตอรธรุ กิจ วิทยาลัยฟารอ ีสเทอรน
บทท่ี 5 Objects และ Classes 155เร่มิ ตน กับ Javaการ overload methodเน่อื งจากวา constructor ก็เปน method ชนิดหนงึ่ ดงั น้นั ถา เราสามารถทีจ่ ะ overload constructor ไดเรากส็ ามารถทจ่ี ะ overload method ไดเ ชนกัน เพราะฉะนัน้ เราจะมาดเู รอ่ื งการ overload method ซ่งึ ก็ไมแ ตกตางจากการ overload constructor เทา ใดนกั เรามาเริ่มตนดวย method ทีแ่ สดงผลออกทางหนา จอ จากตวั แปรชนดิ ตา ง ๆ ทส่ี งเขา ไปยัง method นี้//Overload.javaclass Ball { private double x, y, z;//constructorBall() { x = y = z = 0.0;} //display coordinates public void display() { System.out.println(\"(\" + x + \", \" + y + \", \" + z + \")\"); }}class Overload {public static void main(String[] args) { Ball ball = new Ball(); //create object display(25); //display int display(350.0); //display double display(\"I love overloading.\"); //display string display('A'); //display char display(ball); //display object}//accept int as a parameterpublic static void display(int data) { System.out.println(data);}//accept double as a parameterpublic static void display(double data) { System.out.println(data);}//accept string as a parameterpublic static void display(String data) { System.out.println(data);}//accept char as a parameterpublic static void display(char data) { System.out.println(data);}//accept object as a parameterpublic static void display(Ball blue) { blue.display(); //calling display() from class Ball} ภาควิชาคอมพิวเตอรธ ุรกิจ วิทยาลัยฟารอสี เทอรน
บทท่ี 5 Objects และ Classes 156เริ่มตนกบั Java}โปรแกรม Overload.java สรา ง method display() เพ่ือรองรบั parameter ตาง ๆ จาํ นวน 5 ตัว คือ รับint รับ double รับ string รบั char และรบั object และกเ็ ชน เดยี วกับการ overload constructor methodทเ่ี ราเขียนข้นึ ตา งก็มี signature ที่ไมเหมอื นกนั ดงั นั้น java ก็สามารถหา method ทถี่ ูกตอ งตามการเรียกใช ผลลัพธท่ไี ดจ ากการ run โปรแกรมคอื25350.0I love overloading.A(0.0, 0.0, 0.0)การใช overload นัน้ มีขอ ดีในการเขยี นโปรแกรมคอื เราไมจ าํ เปน ตอ งหาชอ่ื อืน่ ๆ ทีเ่ หมาะสมกับหนา ท่ีของ method นนั้ ๆ นอกเหนือจากท่เี ราไดเลอื กไวแลว และการใชชื่อเดยี วเพอื่ รองรบั parameter หลายตวั ทาํ ใหผ ใู ชไ มต อ งคนหา method ตัวอ่นื ท่ีทาํ หนา ท่แี บบเดยี วกนั ตัว Java เองก็ไดส รา ง method ไวมากมายที่มกี ารใช overload ในการสรางเพอื่ รองรบั การใชง านของ user ทม่ี ีความหลากหลายของขอ มลูที่สง เขา ไปยัง method นัน้ ๆ ทาํ ใหผใู ชไมต อ งเสยี เวลาในการคน หา method ทต่ี ัวเองตอ งการใชผูอา นควรฝกการเขยี นโปรแกรมดว ยการใช overload method เพ่อื ใหเ กิดความชาํ นาญ และเขาใจถึงวิธกี ารของ method overload มากยงิ่ ข้ึนการสรา ง class ภายใน class (nested class)ตวั อยางของการสรา งและเรยี กใช class ทเ่ี ราไดทราบถึงกอ นหนา นี้ เปน การสรา ง class ทม่ี เี พียงเฉพาะตวั แปร และ method อยภู ายใน class เทานน้ั ยงั ไมมขี อ มูลภายใน class ที่ตัวมนั เองกเ็ ปน classเชน เดียวกัน เราจะมาดูถงึ วิธีการสราง class ภายใน class อยางงาย ๆ เพ่ือใหไ ดร บั ทราบวา Java ยอมใหมีการสราง class ภายใน class เชน เดียวกันกบั ทเี่ ราสามารถสราง method อื่น ๆเราจะลองเขยี นโปรแกรมตวั อยา งแบบงา ย ๆ ที่ class ซอ นกันอยู//NestedClass.javaclass Parent { //create a Child object private String name; Child c = new Child(\"Galvin\"); Parent(String n) { name = n; } public void showName() { System.out.println(\"Parent: \" + name); c.showName(); //calling Child's showName() } class Child { private String name; //create a GrandChild object GrandChild gc = new GrandChild(\"Jeff\"); Child(String n) { name = n; } public void showName() { System.out.println(\"Child: \" + name); gc.showName(); //calling GrandChild's showName() ภาควิชาคอมพิวเตอรธรุ กิจ วิทยาลัยฟารอสี เทอรน
บทท่ี 5 Objects และ Classes 157เริ่มตนกับ Java } class GrandChild { private String name; GrandChild(String n) { name = n; } public void showName() { System.out.println(\"GrandChild: \" + name); } }//class GrandChild }//class Child}//class Parentclass NestedClass { public static void main(String[] args) { Parent p = new Parent(\"Rebecca\"); p.showName(); }}โปรแกรม NestedClass.java สราง object จาก class Parent หนึ่งตวั แสดงขอมลู ทอี่ ยใู น class ผานทาง method showName() ซ่งึ ใหผ ลลพั ธ ดงั น้ี คือParent: RebeccaChild: GalvinGrandChild: Jeffclass Parent ของเราไดสรา ง class อีก class หน่ึงทอ่ี ยูภายในชอื่ Child และ class Child ก็ไดสรางclass อกี class หน่ึงช่ือ GrandChild โดยทกุ class จะมี method ชือ่ showName() ซง่ึ เอาไวใชในการแสดงคาของตวั แปรของแตละ class ไปยงั หนาจอ เราไดส รา ง object จาก class Child ภายใน classParent ช่ือ c และเราเรยี ก method showName() ของ class Child จาก method showName() ของclass Parent ในทํานองเดียวกันร าก็ไดส รา ง object จาก class GrandChild ภายใน class Child และก็เรียก method showName() ของ class GrandChild จาก method showName() ของ class Childดว ย เพราะฉะนนั้ ขัน้ ตอนของการ execute คอืParent.showName() Æ Child.showName() Æ GrandChild.showName()เราสามารถทจ่ี ะสรา ง object จาก class ทอ่ี ยูดา นในผานทาง object ท่ีอยูดา นนอก ดงั เชนตวั อยา งนี้class NestedClass { public static void main(String[] args) { Parent p = new Parent(\"Rebecca\"); p.showName(); Parent.Child newChild = p.new Child(\"John\"); Parent.Child.GrandChild newGrandChild = newChild.new GrandChild(\"Jen\"); newChild.showName(); newGrandChild.showName(); }} ภาควิชาคอมพิวเตอรธ รุ กจิ วทิ ยาลัยฟารอ ีสเทอรน
บทท่ี 5 Objects และ Classes 158เรม่ิ ตน กบั Javaเราเพ่มิ ประโยคใหมเ ขา กบั class NestedClass ของเราเพ่อื แสดงการสรา ง object จาก class ทอ่ี ยูภ ายในประโยคParent.Child newChild = p.new Child(\"John\");สรา ง object จาก class Child ผา นทาง object ทมี่ าจาก class Parent ดว ยการเรียกใช p.newChild(\"John\") เราตองทําการสรา งผา นทาง object ของ class Parent เทาน้นั เราไมส ามารถทจี่ ะสรา งobject จาก class Child ผานทาง class Parent โดยตรง เชน ประโยคParent.Child newChild = Parent.new Child(\"John\");จะไมไดร ับการ compile และ Java จะฟองดว ย error ทันทีการสราง object จาก class GrandChild ผา นทาง class ท่ีอยภู ายนอกทงั้ สองกค็ ลาย ๆ กันผลลัพธของการ run โปรแกรมทถี่ กู ดัดแปลงแลว คือParent: RebeccaChild: GalvinGrandChild: JeffChild: JohnGrandChild: JeffGrandChild: Jenเนอื่ งจากวา เราสรา ง object ของ class Child ผานทาง class Parent ดงั นน้ั เมอื่ เรียกใช methodshowName() เราจงึ ไดผ ลลพั ธChild: JohnGrandChild: Jeffอีกครง้ั หน่งึ สว น object ทส่ี รา งขึ้นใหมจ าก class GrandChild เมื่อเรียก method showName() เราจงึไดเ พียงแต GrandChild: Jen เทาน้ันตัวอยางโปรแกรมการสรา ง nested class ทเ่ี หน็ เปนเพยี งแคตวั อยา งทแี่ สดงใหด ถู งึ การสรา ง nestedclass เทา น้นั การออกแบบ nested class ตองคาํ นึงถงึ ความสมั พันธข องทงั้ class ที่อยดู า นนอก และclass ที่อยดู านในวามีความสมั พนั ธกนั อยางไร ถา ความสมั พนั ธน้นั สามารถที่จะเขยี น class แยกกนัออกมาได การออกแบบก็ควรใหเปน class ทแ่ี ยกกันอยู เพราะจะทําใหก ารออกแบบทําไดง า ยกวา การสรางและเรยี กใช object ก็จะไมซ ับซอ นเทาใดนักมาถึงตอนนีเ้ ราไดทราบถงึ การสรา ง class การออกแบบ method และการสราง object จาก classพอสมควร ตวั อยางทจ่ี ะแสดงใหดตู อ ไปเปนความพยายามทจ่ี ะออกแบบ class Array ขึ้นมาใชงานเพือ่ ทจ่ี ะแสดงใหเห็นถึงศกั ยภาพของการใช Java ในการเขยี นโปรแกรมclass MyArray ทเี่ ราสรา งข้นึ จะกําหนดใหเ ปน array ท่ีใชเกบ็ Object เพอ่ื ใหม คี วามยดื หยนุ ในการทํางานกบั ขอ มลู ตา ง ๆ ทั้งนแี้ ละทง้ั นนั้ class MyArray เปนเพียงแคต วั อยา งตัวอยางหนึ่งเทา นัน้ ผอู า นสามารถทจี่ ะทาํ ไดมากกวาทีโ่ ปรแกรมตัวอยางนแี้ สดงใหด ู//MyArray.javaclass MyArray { //array of objects Object []arr; //maximum size of array int maxSize; //number of items in array int count;//default constructorMyArray() { ภาควิชาคอมพิวเตอรธรุ กจิ วทิ ยาลัยฟารอ ีสเทอรน
บทที่ 5 Objects และ Classes 159เริม่ ตน กับ Java count = 0; //no item as yet maxSize = 10; //default maximum size arr = new Object[maxSize]; //allocate space for arr}//constructorMyArray(int size) { count = 0; //no item as yet maxSize = size; //set maximum size arr = new Object[maxSize]; //allocate space for arr}//method to add item into arrpublic void add(Object item) { //expand capacity if arr is full //double the size if(count == maxSize) { //double arr's size maxSize *= 2; //create temporary array Object []temp = new Object[maxSize]; //copy items into new array: temp System.arraycopy(arr, 0, temp, 0, arr.length); //refer arr to temp arr = temp; } arr[count++] = item; //add new object into arr}//overload method add to accomodate doublepublic void add(double item) { add(String.valueOf(item));}//overload method add to accomodate intpublic void add(int item) { add(String.valueOf(item));} //return formatted output when user uses System.out.println() //10 items per line public String toString() { //create new buffer to hold data StringBuffer buffer = new StringBuffer(); for(int i = 0; i < maxSize; i++) { //append newline if this line already has 10 items if(i % 10 == 0) buffer.append(\"\n\"); //stop appending when there is no item left (null) if(arr[i] == null) break; //append tab + item in arr buffer.append(\"\t\" + arr[i]); } //returning an output String return new String(buffer + \"\n\"); }} ภาควิชาคอมพิวเตอรธุรกจิ วิทยาลัยฟารอ ีสเทอรน
บทท่ี 5 Objects และ Classes 160เริม่ ตนกบั Javaเรากาํ หนดใหมี constructor สองตัว โดยท่ตี วั แรกเปน default constructor ที่กาํ หนดใหข นาดของarray มีความจคุ ร้งั แรกไดเ พยี ง 10 ตัว สวนตวั ทส่ี องเปน constructor ทผ่ี ูใชสามารถกาํ หนดขนาดของarray ได เราไดออกแบบให array ของเราเปน array แบบยืดหยนุ หรอื ทเี่ รยี กวา dynamic array โดยเรากาํ หนดใหม กี ารขยายขนาดของ array ใหเปน สองเทาของขนาดเดมิ ถา มกี ารใสข อ มูลเกนิ จํานวนที่array สามารถรองรบั ได ใน method add()public void add(Object item) { //expand capacity if arr is full //double the size if(count == maxSize) { //double arr's size maxSize *= 2; //create temporary array Object []temp = new Object[maxSize]; //copy items into new array: temp System.arraycopy(arr, 0, temp, 0, arr.length); //refer arr to temp arr = temp; } arr[count++] = item; //add new object into arr}method add() ของเราจะตรวจสอบคา ของ count (จาํ นวนของขอมลู ที่มอี ยใู น array) กบั maxSize(ความจสุ ูงสดุ ทสี่ ามารถเกบ็ ขอ มูลได) วา เปน คาเดียวกนั หรอื ไม ถาเปนคา เดียวกันเราจะขยายขนาดของarray ออกเปน สองเทา ดว ยการสราง array ตัวใหมช อ่ื temp ท่มี คี วามยาวเปน สองเทาของ array ตัวเดิมmaxSize *= 2;Object []temp = new Object[maxSize];หลงั จากนั้นเราก็ทําการโยกยายขอ มลู จาก array ตวั เกา สู array temp ดวยการใชค าํ ส่งัSystem.arraycopy(arr, 0, temp, 0, arr.length);คําส่ังนจ้ี ะทาํ การยายขอ มูลจาก arr เริ่มตน ท่ี index = 0 ไปสู temp เรม่ิ ตนที่ index 0 จนกวาจะหมดความยาวท่กี าํ หนดให (arr.length) ซง่ึ ก็คือจาํ นวนของขอมูลท่ีอยใู น arr ทัง้ หมดเมอ่ื โยกยา ยขอ มลู เสรจ็ แลว เรากอ็ า งถงึ array ตัวใหมด ว ย array ตัวเดมิ ของเราคอื arr ดวยคาํ ส่ังarr = temp;เรายังไดท าํ การ overload method add() ของเราเพ่ือใหสามารถรองรบั การเพิ่มขอ มูลทีเ่ ปน double และint เขาสู array ของเราได วิธีการแบบน้ไี มค อ ยจะดสี ักเทาไร เพราะเปนการนําเอาขอมูลทไี่ มใชช นดิเดียวกัน (โดยตรง) เขาไปเกบ็ ไวใน array ซง่ึ ถา หากมีกระบวนการอ่นื ๆ ท่ีเราตองการทาํ กบั ขอมูลเหลาน้นั เราจะตอ งเสยี เวลาในการตรวจสอบชนิดของขอ มูลทุกตวั ท่มี อี ยใู น array ของเราเราทําการ overload ดวยการใช method ของ class String คอื String.valueOf() ดังท่ีเห็นนี้public void add(double item) { add(String.valueOf(item));}เนอื่ งจากวา String เปน Object ชนิดหนึ่งดงั นน้ั การ add String เขา สู array ของเราจึงไมม ปี ญหาอะไรหลงั จากนน้ั เราไดเขยี นโปรแกรมเพ่อื ตรวจสอบ ดงั นี้ ภาควิชาคอมพิวเตอรธรุ กจิ วิทยาลยั ฟารอ ีสเทอรน
บทท่ี 5 Objects และ Classes 161เริม่ ตนกบั Java//TestMyArray.javaimport java.lang.Integer;class TestMyArray { public static void main(String[] args) { //create array of 10 objects MyArray array = new MyArray(10); //add 40 objects into array (randomized) int count = 0; while(count < 40) { int data = (int)(Math.random() * 100 + 1); array.add(new Integer(data)); ++count; } System.out.println(array); //display contents array.add(45.23); //add double array.add(88.23); array.add(89); //add int array.add(12); System.out.println(array); }}เราก็ไดผลลัพธ ดังน้ี 9 76 20 86 98 12 27 35 41 31 54 65 83 3 36 96 24 63 19 75 3 91 87 72 3 12 7 46 96 11 1 70 27 47 14 51 22 74 95 98 9 76 20 86 98 12 27 35 41 31 54 65 83 3 36 96 24 63 19 75 3 91 87 72 3 12 7 46 96 11 1 70 27 47 14 51 22 74 95 98 45.23 88.23 89 12ผอู านควรสงั เกตถึงผลลพั ธท ไี่ ดโดยเฉพาะขอมลู ในบรรทดั สดุ ทาย (ท่เี ราไดเ พิม่ ขอมลู ทีเ่ ปน double และint หลังจากการ display ครัง้ แรก)สว นประกอบทส่ี ําคญั อีกสวนหน่ึงท่ีตองกลาวไวใ นท่ีนี้ คอื method toString() และกอนทจี่ ะพูดถึงmethod toString() เราควรดปู ระโยคอีกประโยคหน่งึ กอ น นน่ั กค็ อืSystem.out.println(array);ประโยค System.our.println() จะรับเฉพาะขอ มูลที่เปน String หรอื primitive datatype ทเ่ี ราไดพดู ถงึกอ นหนา น้ี แตส ิง่ ที่เราสง ไปใหเ ปน object จาก class MyArray ทาํ ไมเราถงึ ทําได?เราสง Object ไปให System.out.println() ไดกเ็ พราะวา เราไดเขียน method toString() รองรับไวเรยี บรอ ยแลว เม่ือไรกต็ ามที่ Java เห็นขอมูลทีไ่ มใ ช String หรือ primitive datatype Java จะทําการคนหา method toString() ถา มี Java ก็จะใช method toString() น้นั แตถ า ไมม กี ็จะฟองดว ย errorทนั ที เรามาดกู นั วาเราเขยี น method toString() อยา งไร ภาควิชาคอมพิวเตอรธรุ กจิ วทิ ยาลัยฟารอสี เทอรน
บทที่ 5 Objects และ Classes 162เร่ิมตนกบั Javapublic String toString() { //create new buffer to hold data StringBuffer buffer = new StringBuffer(); for(int i = 0; i < maxSize; i++) { //append newline if this line already has 10 items if(i % 10 == 0) buffer.append(\"\n\"); //stop appending when there is no item left (null) if(arr[i] == null) break; //append tab + item in arr buffer.append(\"\t\" + arr[i]); } //returning an output String return new String(buffer + \"\n\");}ภายใน method toString() เราใช StringBuffer ในการเกบ็ สว นประกอบตาง ๆ ท่เี ราตองการสงกลับออกไป ซ่ึงจะประกอบไปดว ย ขอมลู ตา ง ๆ ทอ่ี ยใู น array (arr[i]) tab (\t) newline (\n)เรานาํ ขอ มูลเหลา น้ไี ปเกบ็ ไวใน buffer ดวยการใช method append() ทกุ ๆ ครัง้ ทีเ่ ราไดข อ มลู ครบ 10ตวั เราจะทาํ การ append newline เขา สู buffer ถาหากวา เราไดขยายขนาดของ array แตไ มไ ดใสข อ มลูครบตามขนาดท่ไี ดข ยายข้นึ เราจะยุติการนาํ ขอ มลู เขาสู buffer เนื่องจากวาขอมลู เหลา นม้ี คี า เปน nullและเรากไ็ มต อ งการแสดงคา เหลาน้ี เม่ือเราไดขอมลู ท้ังหมดท่ีตอ งการแลว เรากส็ ง กลบั ออกไป โดยสงออกไปในรูปแบบของ String (เพราะ System.out.println() ตองการ String) ดว ยคําสงั่return new String(buffer + \"\n\");ผูอา นสามารถนาํ เอาเทคนคิ นีไ้ ปใชกบั การแสดงขอมูลอ่ืน ๆ ผา นทาง System.out.println() ไดโดยไมม ีขอ จํากัดใด ๆ ทั้งสนิ้เราสามารถทจ่ี ะสรา ง class เพ่อื การใชงานของเราโดยไมมขี ีดจาํ กัดใด ๆ ทั้งน้กี ็ตอ งขึ้นอยกู ับลกั ษณะงานนัน้ ๆ วา อยใู นรปู แบบไหน ความยาก งา ยของงานเปนอยางไร ตัวอยา งการสรา ง array ขึ้นมาใชงานเปนเพียงตวั อยา งเลก็ ๆ เพยี งตัวอยา งเดยี วที่เราไดแ สดงใหด ถู งึ ขอ ดขี องภาษา Java ยังมสี ่งิ อนื่ ๆ ที่ผูอา นสามารถทจ่ี ะสรา งข้นึ มาสาํ หรบั งานของตัวเองไดPackagePackage เปนทีร่ วมของ class ตาง ๆ ท่ีถกู เรยี กใชใ นโปรแกรม หรือ method ตา ง ๆ class ทกุ ๆ ตวั ของJava ไดถูกจัดถูกเก็บอยใู น package ตา ง ๆ เชน java.lang หรอื java.io การเอา class ตา ง ๆ มารวมกนัไวใน package เดียวกันทาํ ใหก ารเรยี กใช class ตา ง ๆ เหลา นที้ ําไดง ายขึน้ ถาผูอ านมองยอ นกลับไปดูโปรแกรมตัวอยา งตาง ๆ ที่เราเขียนขึน้ ก็จะเหน็ การเรียกใช package เหลา นใ้ี นโปรแกรมหลาย ๆ ตัว เราจะมาดถู งึ วธิ กี ารสราง package เพื่อเก็บ class และการเรยี กใช package เหลา น้ใี นโปรแกรมตัวอยา งการสรา ง packageการสรา ง package นน้ั ไมย าก ขัน้ ตอนก็ไมซ ับซอนเทาไร ขน้ั ตอนแรกทเี่ ราตอ งทํากค็ อื ใสค ําวาpackage ตามดว ย ชื่อของ package น้ันกอนประโยคใด ๆ ในไฟลท ี่เก็บ class นนั้ ๆ ท่ีเราสรา งข้นึ(ยกเวนประโยคที่เปน comment) เชน//package Shapepackage Shape; ภาควิชาคอมพิวเตอรธุรกจิ วทิ ยาลัยฟารอสี เทอรน
บทท่ี 5 Objects และ Classes 163เรม่ิ ตน กับ Javapublic class Rectangle { … …}ถา เราไมใสคาํ วา public ไวด านหนา ของ class หรือ method ที่อยูใน package ทเ่ี ราสรางขนึ้ โปรแกรมหรอื class ตัวอนื่ ๆ ท่อี ยูนอก package ก็ไมสามารถทีจ่ ะเรยี กใช class นไ้ี ด ยกเวน class อื่น ๆ ที่อยใู นpackage นีเ้ ทาน้ัน package ตวั อยา งของเราใชช ื่อวา Sample โดยเรากาํ หนดให Sample ประกอบไปดวย class One และ class Two และเราไดส ราง package อกี ตวั หนงึ่ ใน Sample ใหช่อื วา oneMoreและใน package oneMore นเ้ี ราจะเก็บ class Three ไว ดังท่เี ห็นจาก code ขางลางน้ี//sample packagepackage Sample;public class One { public One() { System.out.println(\"This is class One in Sample package.\"); }}//sample packagepackage Sample;public class Two { public Two() { System.out.println(\"This is class Two in Sample package.\"); }}//sample packagepackage Sample.oneMore;public class Three { public Three() { System.out.println(\"This is class Three in Sample.oneMorepackage.\"); }}ในการ compile ไฟลท ั้งสามทีไ่ ดส รางข้ึนน้ี เราใชค าํ ส่งั javac -d e:\bc221Book\source ตามดวยช่อืไฟล เชน javac -d e:\bc221Book\source One.javaเราตอ งใช option -d ในการ compile ไฟลท งั้ สามเพอื่ บอกให Java รูถึงแฟม ปลายทางที่เราตองการเกบ็class ไฟลที่เกดิ ข้ึนจากการ compile ในท่ีน้เี ราจะเก็บ class ไฟลไวใ น e:\bc221Book\sourceภายในไฟล One.java และ Two.java เราไดใ ชค าํ สง่ั package Sample เปนตัวบอกถึงทเ่ี ก็บ class ไฟลและในตวั ไฟล Three.java เราใชค ําสัง่ package Sample.oneMore เพราะฉะนั้น class ไฟลท ่ีเกิดขึ้นจะถูกเก็บไวในแฟม (directory) เหลา น้ี ดงั ท่ไี ดแ สดงไวในรูปทเี่ ห็นดานลางน้ี ภาควิชาคอมพิวเตอรธุรกจิ วทิ ยาลัยฟารอสี เทอรน
บทท่ี 5 Objects และ Classes 164เรมิ่ ตนกบั Java Package ชอ่ื Sample ใน e:\bc221Book\source Package ชอ่ื oneMore ใน e:\bc221Book\source\Sample Class ไฟลท ถ่ี กู สรางข้ึนรปู ท่ี 5.7 แฟมเกบ็ class file ทเ่ี กดิ ข้นึ จากการ compile ดวย option -dหลงั จากน้ันเรากส็ รา งโปรแกรมตรวจสอบการเรยี กใช package ที่เราไดส รา งขน้ึ โดยทีเ่ รากําหนดใหม ีการเรยี กใช class ตาง ๆ ดว ยการใชค าํ สั่ง import ดังน้ี//test the packageimport Sample.One;import Sample.Two;import Sample.oneMore.Three;class TestPackage { public static void main(String[] args) { One object1 = new One(); Two object2 = new Two(); Three object3 = new Three(); }}หลงั จากนน้ั เราก็ compile โปรแกรม TestPackage.java ดว ยคาํ สง่ัjavac -classpath e:\bc221Book\source TestPackage.javaโดยเราใช option –classpath ตามดว ยท่อี ยขู อง class ตา ง ๆ ทเ่ี ราไดส รา งข้ึนในการ compile และเมือ่ทดลอง run ดผู ลลัพธท ไ่ี ดค อืThis is class One in Sample package.This is class Two in Sample package.This is class Three in Sample.oneMore package.ในการสราง package นัน้ Java จะไปสรางแฟมทมี่ ชี อ่ื เหมือนกบั ทเี่ รากาํ หนดไว ดังทไี่ ดเ ห็นในตวั อยางและเราสามารถที่จะกาํ หนด sub-directory ดว ยการใช . (dot) เชน ทีเ่ ราไดท าํ ไว (Sample.oneMore)และเราตองไมล มื ใชค ําวา public นาํ หนา class และ method ตา ง ๆ ที่เราตอ งการใหโปรแกรม หรอืclass หรือ method อ่นื ๆ ทีอ่ ยูนอก package ใชเราไมจ าํ เปน ตอ ง compile ดว ยการใชคาํ ส่งั ทมี่ ี option –classpath ในการ compile โปรแกรมทเี่ รียกใชpackage ตาง ๆ ของ Java เพราะ Java ไดจดั การเรอ่ื งตา ง ๆ เหลา นใ้ี หเ ราเรียบรอ ยแลวถาเราใช class ตาง ๆ ท่ีอยใู น package ท่สี รา งข้ึนบอยคร้ัง หรอื ทุกคร้ัง เรากส็ ามารถที่จะกาํ หนดใหJava คน หา class ตา ง ๆ เหลา น้โี ดยไมต องกําหนด option –d ในการ compile เราเพยี งแตก ําหนดclasspath ไวก อนการ compile ครัง้ แรกเพียงครง้ั เดยี ว ดังนี้ ภาควิชาคอมพิวเตอรธ ุรกจิ วทิ ยาลยั ฟารอสี เทอรน
บทท่ี 5 Objects และ Classes 165เร่มิ ตน กบั Javaset classpath=e:\bc221Book\sourceถา เราไมอยากทจี่ ะกําหนด classpath ทกุ ครงั้ ที่เราตอง compile เราก็กาํ หนด classpath ไวใ นไฟลautoexec.bat สาํ หรบั Windows รนุ เกา ๆ สว น Windows รนุ ใหมเราตอ งกําหนด classpath ไวใ นenvironment variables (คลา ย ๆ กบั การกาํ หนด path ของ Java ในบทที่หนง่ึ ) ถาเรามี package อืน่ ๆท่เี ราตอ งการใช เราก็ใช ; เปนตวั แบง classpath เชนset classpath=e:\bc221Book\source; c:\myOthers\Shapeสรปุในบทนเ้ี ราไดสาํ รวจถึงวิธีการสรา ง class การสราง object การสราง method และการสราง method และconstructor ทมี่ ี signature ท่แี ตกตางกนั ในการรองรับการเรยี กใชด ว ย parameter ท่ตี า งกนั การกาํ หนดนโยบายการเขา หาขอมลู ท่ีอยใู น class รวมไปถึงการสราง nested class และการสราง package โดยสรปุ แลวเราไดท ราบถงึ9 สวนประกอบของ class9 ช่อื ของ class จะตองเปนช่ือเดียวกันกับๆฟลท เี่ ก็บ class น้นั อยู9 การประกาศตัวแปรทเี่ รียกวา class variable ตอ งใชค าํ วา static นําหนา9 ตัวแปรที่เปน instance variable สามารถท่จี ะเขา หาไดผ านทาง object ที่เกดิ จาก class น้ัน9 การสรา ง method จะตองบอกถงึ สิ่งทีต่ อ งสง กลบั ชนิดและจํานวนของ parameter (ถาม)ี9 Method ท่ีประกาศใหเ ปน static สามารถถกู เรยี กใชไดถงึ แมว า จะไมมี object ใด ๆ ถูกสรางขนึ้9 การเขาหาขอ มลู ใน class มีสามแบบคอื private public และ protected (ไมนบั แบบทไี่ มมคี าํ ใด ๆ นาํ หนา)9 การสราง class สามารถท่ีจะสรางใหอยูใ น class อนื่ ได9 การสรา ง และ การใช package จะตอ งใชคาํ วา public นาํ หนา class หรอื method ที่ตองการให ผูอื่นทอ่ี ยูนอก package ใชแบบฝก หดั1. จงออกแบบ class ทใ่ี ชเ ก็บขอ มูลเกย่ี วกบั นักศึกษา เชน รหัส ช่อื -นามสกลุ ทอี่ ยู และขอ มูลอื่น ๆ ที่ เหน็ วา เหมาะสม ใหเขยี นโปรแกรมทดสอบการสรา ง object ตา ง ๆ จาก class ทีไ่ ดส รางขนึ้ นี้2. จงออกแบบ class ที่ใชเ ก็บขอ มลู ทีเ่ กี่ยวขอ งกบั นา้ํ หนกั เชน ตัน กโิ ลกรมั และ กรัม โดยใหอ อกแบบ ใหม ี constructor ทรี่ องรับการสรา ง object ดว ยจาํ นวน parameter ท่ตี า งกนั ชนิดของ parameter ที่ตา งกัน รวมไปถึงการออกแบบ method ทท่ี ําการบวก การลบ object ตาง ๆ ทไ่ี ดถูกสรา งข้ึน ให เขยี นโปรแกรมทดสอบ3. จาก class MyArray ทส่ี ามารถเก็บขอ มลู ที่เปน object ตางชนดิ กันได จากตวั อยางทใี่ หไ ว จงเขียน method ท่ีสงจาํ นวน object ที่มีอยูใน array ใหช่อื วา getCount() และ method dataAt() ทสี่ ง คา ของขอ มลู ณ ตาํ แหนง ท่ีกาํ หนดใหก ลบั ไปยงั ผูเ รียก เชน ถา เรยี กดวย Object obj = arr.dataAt(7); จะสงขอ มลู ณ ตาํ แหนงที่ 7 มาใหกบั ตวั แปร obj ใหเ ขียนโปรแกรมทดสอบ method ทเี่ ขยี นข้นึ4. จงเขยี นโปรแกรมที่มี method ในการคํานวณหาพืน้ ที่ของวงกลมทีม่ ี parameter ตา งชนดิ กนั เชน ผู เรียกใช method อาจสง ขอ มูลท่มี ชี นดิ เปน int double float หรือ String ท่ีเปนตัวเลข เชน \"234\" ใหเขยี นโปรแกรมตรวจสอบ method เหลา น้ี5. จงเขยี นโปรแกรมทต่ี รวจสอบการใช overloaded constructor ในการกาํ หนดคาใหกับ instance variable ทีม่ ีอยูใน class นน้ั ๆ ใหเขียนโปรแกรมทดสอบ ภาควิชาคอมพิวเตอรธุรกิจ วิทยาลยั ฟารอ ีสเทอรน
บทที่ 5 Objects และ Classes 166เริม่ ตน กบั Java6. จงออกแบบ class สําหรับเกบ็ ขอ มูลทเี่ กี่ยวขอ งกบั นักศึกษา เชน รหสั ประจาํ ตวั ช่อื นามสกลุ ทีอ่ ยู และขอ มลู อื่น ๆ ทจ่ี าํ เปน รวมไปถงึ method ตาง ๆ ที่ใชใ นการกาํ หนดคา หรอื ประมวลผลเกรดเฉลยี่ และ method สําหรบั การแสดงผลไปยังหนา จอ7. จงออกแบบ class สาํ หรบั เก็บขอ มูลของ วนั เดอื น ป ในรปู แบบของ dd:mm:yyyy โดยกาํ หนดให ขอมลู นน้ี าํ เขามาจาก keyboard ใหเขยี น Method ทีท่ าํ หนา ทใ่ี นการเปล่ยี นขอ มูลนี้ใหอ ยใู นรปู แบบ ที่ขนึ้ ตนดวย วนั ตามดวย วนั ที่ เดือน และ ป เชน วนั จนั ทรท ี่ 12 สิงหาคม พ.ศ. 2546 หรอื Monday 12 August 2003 ใหเขียนโปรแกรมทดสอบ8. จงออกแบบ class Matrix สาํ หรบั การประมวลผลตา ง ๆ เชน การบวก การลบ การคณู และ กระบวนการอน่ื ๆ ทีเ่ กี่ยวขอ ง ใหเขียนโปรแกรมทดสอบ9. จงออกแบบ class ท่ใี ชส าํ หรบั การคํานวณหาอายุของ user ทใ่ี สเ ขามาจาก keyboard ในรปู แบบ ของ dd/mm/yyy โดยใหผลลพั ธท ห่ี าไดอยูใ นรปู แบบของ จาํ นวนของวนั ทง้ั หมด ใหเ ขยี นโปรแกรม ทดสอบ10. จงออกแบบ class MyString ท่ีมี method สําหรบั การประมวลทเี่ กย่ี วของกบั string ตาง ๆ เชน การ บวก string สองตวั การคน หาคาํ ใน string การลบคาํ ทอ่ี ยูใ น string การนับจํานวนตวั อักษรท่ีอยใู น string ใหเ ขยี นโปรแกรมทดสอบ ภาควิชาคอมพิวเตอรธ ุรกิจ วทิ ยาลัยฟารอีสเทอรน
เราไดพ ูดถงึ การสรา ง class และสวนประกอบตา ง ๆ ทสี่ าํ คญั ของ class รวมไปถึงการสรา ง method ในบททหี่ า สาํ หรบั บททหี่ กน้ีเราจะสํารวจในเรื่องของการสรา ง class ใหมจาก class เดมิ ท่มี ีอยู การนําเอาสว นประกอบของ class เดมิ มาใชใน class ใหม การถา ยทอดคณุ สมบตั แิ ละ กระบวนการตา ง ๆ จาก classเดมิ สู class ใหมหลังจากจบบทน้ีแลว ผอู านจะไดทราบถงึ เรือ่ งของ o การใช class เดมิ สาํ หรับการสรา ง class ใหม (Extended class) o การถายทอดคณุ สมบัติ (Inheritance) o คุณสมบตั ิ และการใชประโยชนจ าก polymorphism o การสราง abstract class และ abstract method o การใช และ การสรา ง interfaceการสราง class ใหมจาก class เดิมทม่ี อี ยแู ลวเปนการพัฒนาโปรแกรมทท่ี ําใหก ารเขียน code ใชเ วลานอ ย และเปนการใช code อยางคุมคาทส่ี ดุ Java ยอมใหมีการสราง class เดิมจาก class ใหมไดอยา งงาย ๆ โดยทผี่ ูเขยี นโปรแกรมแทบจะไมตอ งทาํ อะไรมากมาย (ยกเวน code ใหมท ่เี ขยี นขน้ึ ) กอนทีจ่ ะพดูถงึ ศัพทตาง ๆ ที่เกี่ยวขอ งกบั การสราง class ใหมจาก class เดิมเราจะมาดกู ันถึงตวั อยางของการสรา งclass ใหมจาก class เดมิ กอ นเราจะเริ่มตนดวยการสรา ง class งา ย ๆ class หนึง่ ทเี่ กี่ยวกับรถทใ่ี ชเ คร่ืองยนต (motor vehicle) โดยกาํ หนดใหมีขอ มูลทไี่ มซับซอน เชน ยหี่ อ (make) รุน (model) ปท ีผ่ ลติ (year) และ จาํ นวนทน่ี ่ัง (seats)พรอ มทัง้ กาํ หนดใหม ี method สาํ หรับการเขาหาขอมูลเหลานน้ั หลงั จากทไี่ ด class MotorVehicle แลวเราก็ออกแบบ class อ่นื ๆ ทีไ่ ดร บั คณุ สมบตั จิ าก class MotorVehicle ดงั ท่แี สดงใหเหน็ คราว ๆ จากdiagram น้ี (เราจะดโู ครงสรา งของ class ท้ังหมดตอไป) MotorVehicle Car MotorcycleCompact OffRoad Scooter Chopperภาพที่ 6.1 ตัวอยา งของ base-class และ derived-class
บทท่ี 6 การสราง class ใหมจาก class เดิม และ การถา ยทอดคุณสมบตั ิ 168เร่ิมตนกับ Javaเราออกแบบให class MotorVehicle เปน class แมแบบ หรอื ทีเ่ รียกวา parent class (หรอื base classหรือ super class) ซ่ึงจะเปน class ท่อี ยูดานบนสุดของ class ตาง ๆ ในกลมุ นี้ เรากําหนดให classMotorVehicle มี class ลูก (children) อยูสอง class คอื class Car และ class Motorcycle class ลูกท้งัสองตา งก็มี class ทีเ่ ปน ลูกของมนั เองอกี สอง class โดยท่ี class Car มลี ูกเปน class Compact และclass OffRoad สวน class Motorcycle มี class Scooter และ class Chopper เปน class ลกู เราจะกําหนดให class ลูกไดรับคณุ สมบัตจิ าก class แมท ั้งหมด คอื ขอ มลู ทกุ ตวั ทีม่ ีอยูใ น class MotorVehicleเรามาดกู นั ถึง ขอมูล และ method ที่เรากาํ หนดใหม ใี น class MotorVehicle//MotorVehicle.java – Inheritanceclass MotorVehicle { //e.g. Ford, Honda protected String make; //e.g. Taurus, Steed protected String model; //e.g. 2001, 2003. protected int year; //e.g. 4, 2 protected int seats;//constructorMotorVehicle(String make, String model, int year, int seats) { this.make = make; this.model = model; this.year = year; this.seats = seats;}public String getMake() { return make;}public String getModel() { return model;}public int getYear() { return year;} public int getSeats() { return seats; }}เรากาํ หนดใหตวั แปรที่มอี ยใู น class MotorVehicle ใชน โยบายของการเขาหาแบบ protected ซ่ึงเปนการกาํ หนดให class ลกู ทเ่ี กิดขน้ึ จาก class MotorVehicle สามารถท่จี ะเรยี กใชต ัวแปรเหลานี้ได class อน่ื ๆที่ไมไดมาจาก class น้จี ะมองไมเหน็ ขอมูลเหลา น้ี เรากาํ หนดใหมี constructor เพยี งตวั เดียวสาํ หรับการสรา ง object โดยเราเลือกใชค าํ ส่งั this ในการแยกแยะตวั แปรที่อยใู น class กบั ตวั แปรที่เปน parameterMotorVehicle(String make, String model, int year, int seats) { this.make = make; this.model = model; this.year = year; this.seats = seats;}คําวา this เปน คําที่ Java สงวนไวส ําหรบั การบงบอกถงึ object ทไี่ ดรับการกระทําดวยกระบวนการตาง ๆณ เวลานน้ั ๆ เชนในตวั อยางประโยคthis.make = make; ภาควิชาคอมพิวเตอรธ รุ กจิ วิทยาลยั ฟารอสี เทอรน
บทท่ี 6 การสราง class ใหมจ าก class เดมิ และ การถา ยทอดคุณสมบัติ 169เริ่มตน กับ Javaเมื่อ Java ประมวลผล constructor ตวั น้ี Java จะทาํ การกาํ หนดคา จากตวั แปร make ทเี่ ปน parameterของ constructor ใหกับตวั แปร make ท่อี ยใู น class ซงึ่ เปน copy ที่ object ตัวนใ้ี ชอ ยูเราไมจ าํ เปนทจ่ี ะตองใช this เปน ตวั บงบอกตัวแปรเสมอไป ถาเราใชตัวแปรท่อี ยใู น parameter list ที่มีชือ่ ไมเ หมอื นกับ ตัวแปรของ class (เชนตวั อยางอื่น ๆ ทเ่ี ราไดแสดงไวในบททหี่ า) สว น method อนื่ ๆ ท่ีมีอยูกเ็ ปน เพียง method ทสี่ ง คาของตัวแปรเหลานี้ใหก ับผูเรยี ก สําหรับ class อนื่ ๆ ทีเ่ ราไดสรางขนึ้ มีดงั น้ี//Car.java - Derived from MotorVehicleclass Car extends MotorVehicle { protected int doors; Car(String make, String model, int year, int seats, int doors) { super(make, model, year, seats); this.doors = doors; } public int getDoors() { return doors; } //display Car's information as string //using base class methods public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(super.getMake() + \", \" + super.getModel() + \", \" + super.getYear() + \", \" + \" seating: \" + super.getSeats() + \", \" + doors + \"doors.\"); return new String(buffer); }}เราสรา ง class Car จาก class MotorVehicle ดวยการใชค ําสั่ง class Car extends MotorVehicle ซงึ่เปนคาํ ส่ังท่ี Java กาํ หนดใหใชถาตองการสรา ง class ใหมท ตี่ องการใชคณุ สมบตั ิของ class อนื่ภายใน class Car ทีเ่ ราไดสรา งขึน้ เรากาํ หนดใหม ีตวั แปรหนงึ่ ตัวทเ่ี ปนตวั กําหนดจํานวนของประตทู ่ีรถคันนม้ี อี ยู และเพ่ือใหก ารแสดงผลไปยงั หนาจอทําไดง ายข้ึน เราก็สรา ง method toString() สาํ หรับการแสดงผลของ object ทเ่ี กดิ จาก class Car ของเรา เราเรยี กขอมูลท่เี ราไดร บั การถา ยทอดจาก classMotorVehicle ดว ยการใชค ําสงั่ ดงั นี้super.getMake();เม่อื Java เหน็ การใชค าํ สงั่ แบบน้ี Java ก็จะไปคนหา method getMake() ท่ีอยใู น class ท่ีเปน class แมหรือทีเ่ รยี กกันวา super class พรอ มท้ังประมวลผลคาํ ส่งั ตา ง ๆ ทมี่ อี ยใู น method getMake()ผูอ า นจะเหน็ วาเราไมต อ งประกาศตัวแปรขึน้ มาใชใ หมใ น class Car ของเราเลย เราสามารถเรยี กใชต ัวแปรเหลานจี้ าก class MotorVehicle ไดเลย เรามาทดสอบ class ท้ังสองดวยการสราง object จาก classCar สองตวั เชน ท่ีเห็นในโปรแกรม TestVehicle.java น้ี//TestVehicle.javaclass TestVehicle { public static void main(String[] args) { //create two cars, ford and honda ภาควิชาคอมพิวเตอรธ ุรกจิ วทิ ยาลยั ฟารอีสเทอรน
บทที่ 6 การสราง class ใหมจาก class เดิม และ การถา ยทอดคุณสมบตั ิ 170เร่ิมตนกบั JavaCar ford = new Car(\"Ford\", \"Taurus\", 2001, 5, 5);Car honda = new Car(\"Honda\", \"City\", 2003, 4, 4); //display informatin about cars System.out.println(ford); System.out.println(honda); }}ผลลัพธท ีเ่ ราไดจากการ run คือFord, Taurus, 2001, seating: 5, 5 doors.Honda, City, 2003, seating: 4, 4 doors.เราไดใ ชน โยบายการเขาหาแบบทใี่ ชคาํ วา protected ซงึ่ เราไมไดอ ธิบายไวเ ลยกอ นหนา นี้ สาเหตกุ ็เนอ่ื งจากวา คาํ วา protected โดยสว นใหญจะใชก ันในเรือ่ งของการถายทอดคุณสมบตั จิ าก class แมไ ปยังclass ลูก โดยกาํ หนดไววา class ลกู สามารถท่จี ะใชต วั แปร (หรือ method ท่ใี ชคําวา protected นําหนา)จาก class แมไดอ ยางไมมีเงอื่ นไข แตถ าเราใชคาํ วา private แทน class ลกู ไมส ามารถทจ่ี ะเขาหาตวัแปร หรือ method เหลา นไี้ ด ดังตวั อยา งตอไปน้ีCar(String make, String model, int year, int seats, int doors) { super(make, model, year, seats); this.doors = doors; System.out.println(\"base class: \" + super.make);}ใน class MotorVehicle เราเปลย่ี นนโยบายการเขา หาตวั แปร make ใหเปน privateprivate String make;และเพมิ่ ประโยคSystem.out.println(\"base class: \" + super.make);ใน constructor ของ class Car ซ่ึงเปนประโยคทพ่ี ยายามเขา หาตัวแปรใน class MotorVehicle ดวยการใช super.make Java จะไมย อมใหเรา compile พรอมกบั ฟอ งวาเราไมสามารถเขา หาตัวแปรตัวน้ีได วิธีเดียวทเ่ี ราจะเขา หาตัวแปรเหลา นี้ได ก็คอื การเขา ผา นทาง method getMake() ท่ีเราไดกาํ หนดนโยบายการเขาหาใหเ ปน public เทา นน้ัโดยท่ัวไปเรามกั จะกาํ หนดใหต วั แปรทใ่ี ชร ว มกันใน class ลกู (ที่มีอยใู น class แม) ทงั้ หลายมนี โยบายการเขาหาที่เปน แบบ private เพือ่ ปองกันการใชท ไี่ มพงึ ประสงคจ าก class อืน่ และเราก็ควรจะกําหนดใหmethod ทีอ่ ยใู น base class มนี โยบายการเขาหาทีเ่ ปนแบบ protected ดว ยเหตผุ ลเชนเดยี วกนั และเหตุผลอกี อันหนง่ึ กค็ อื คาํ วา protected เมอ่ื มีการนาํ มาใชแ ลว class อ่นื ๆ ที่อยูใ น package เดยี วกนั ก็สามารถทจี่ ะเขา หาตวั แปร หรอื method เหลา น้ีได ดงั นนั้ ถา ตองการให class ตา ง ๆ ของเราทส่ี รา งขน้ึ ในตัวอยางเปน class ท่กี ารใชนโยบายการเขาอยางถกู ตอง เราก็ตองเปลีย่ น class ของเราใหเปน ดงั น้ีclass MotorVehicle {private String make; //e.g. Ford, Hondaprivate String model; //e.g. Taurus, Steedprivate int year; //e.g. 2001, 2003private int seats; //e.g. 4, 2//constructorMotorVehicle(String make, String model, int year, int seats) { this.make = make; this.model = model; this.year = year; ภาควิชาคอมพิวเตอรธ ุรกจิ วิทยาลยั ฟารอ ีสเทอรน
บทท่ี 6 การสรา ง class ใหมจ าก class เดิม และ การถา ยทอดคุณสมบัติ 171เร่ิมตน กับ Java this.seats = seats; } protected String getMake() { return make; } protected String getModel() { return model; } protected int getYear() { return year; } protected int getSeats() { return seats; }}class Car extends MotorVehicle { private int doors; Car(String make, String model, int year, int seats, int doors) { super(make, model, year, seats); this.doors = doors; } protected int getDoors() { return doors; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(super.getMake() + \", \" + super.getModel() + \", \" + super.getYear() + \", \" + \"seating: \" + super.getSeats() + \", \" + doors + \" doors.\"); return new String(buffer); }}เราไมส ามารถทจี่ ะเปลยี่ นนโยบายการเขาหาของ method toString() ใหเ ปน protected ไดก เ็ พราะวาJava ไดกําหนดใหก ารเขาหาของ method toString() เปนแบบ public ไวแลว ซง่ึ เราจะไดอ ธบิ ายตอไปในเร่ืองของการ overrideเพือ่ ใหเ ห็นถงึ ความพิเศษของ การถายทอดคณุ สมบัติ และเพือ่ เปน การแนะนาํ เรื่องของการ override เราจะสรา ง class Compact ข้นึ มาอกี class หนงึ่ โดยกาํ หนดให class Compact นเ้ี ปน class ท่ีไดรบั การถายทอดคณุ สมบัติจาก class Car ดงั นี้//Compact.java Derived from Carclass Compact extends Car { //constructor -using base class (Car) constructor Compact(String make, String model, int year, int seats, int doors) { super(make, model, year, seats, doors); ภาควิชาคอมพิวเตอรธุรกิจ วิทยาลัยฟารอ สี เทอรน
บทท่ี 6 การสราง class ใหมจาก class เดิม และ การถายทอดคุณสมบัติ 172เริ่มตนกบั Java } //override Car's toString() method //presenting Comapct car's details as string public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(\"Compact car: \"); buffer.append(super.toString()); return new String(buffer); }}class Compact ของเราเรยี กใชขอมลู ทกุ อยา งที่ class แมม ใี ห ตวั แรกทเ่ี ราเรียกใชกค็ ือ constructorของ class Car (ซ่ึง constructor ของ class Car ก็เรยี กใช constructor ของ class MotorVehicle) ตวั ท่ีสองท่ีเราเรยี กใชก ็คอื method toString() ของ class Car ซึ่งเราไดเพิม่ คาํ วา \"Compact car: \" ไวก อ นหนาขอมลู อนื่ ๆ ดว ยการใช method append() ของ class StringBuffer ดงั น้ีbuffer.append(\"Compact car: \");buffer.append(super.toString());เม่อื ทดลอง run ดว ยการใชค าํ สงั่Compact honda = new Compact(\"Honda\", \"City\", 2003, 4, 4);System.out.println(honda);ผลลพั ธท ่ไี ด คอืCompact car: Honda, City, 2003, seating: 4, 4 doors.ซ่งึ ตา งจากการ run กอ นหนานี้ (ตอนทเ่ี ราสรา ง object จาก class Car)เราใชเ ทคนคิ ทเี่ รียกวา method overriding ในการแสดงผลขอมลู ของ object ท่เี กิดจาก classCompact ในการ override (ซึง่ ตางกับ overload ทเี่ ราไดท ํากอ นหนานี้ – overload ทาํ กับ method ที่อยูใ น class เดียวกนั และตอ งเปน method ทมี่ ี parameter list ไมเหมือนกัน) method จาก class แมหรอื ทีเ่ รยี กวา base class นนั้ เราสามารถทจี่ ะเขยี น code ใหท ํางานในลกั ษณะใดกไ็ ด โดยท่วั ไปการoverride method ทาํ ใหก ารเรยี กใชง านทาํ ไดง า ยขน้ึ ไมส ับสน เพราะ method ชอ่ื เดียวกนั มีอยใู น classทุกตัว แตท ําหนา ทต่ี ามที่ไดก าํ หนดไวใ น method ของ class นัน้ ๆเราสามารถทจี่ ะ override method ทีม่ อี ยูใ น class แมไ ดทกุ ตวั และ object ท่เี กิดจาก class ลูก หรือท่ีเรียกวา derived class นัน้ เมอ่ื มกี ารเรยี กใช method ที่ไดรบั การ override Java จะไปเรยี ก method ที่อยใู น class ลกู ไมใ ช method ทีอ่ ยใู น class แมจากตวั อยา งของ class Compact ทไ่ี ดกลาวไว เราไดใ ชท ง้ั การถา ยทอดคณุ สมบตั ิ และการ overridemethod โดยเราไดรบั การถา ยทอดในเรือ่ งของตวั แปร และไดใ ชเ ทคนคิ การ override ในการใช methodtoString()Method ทไี่ ดร บั การ override ใน class ลกู นั้นไมสามารถทจ่ี ะเปลี่ยนแปลงนโยบายของการเขาหาใหเ ปนอยางอน่ื ทมี่ คี วามเขม งวดกวาได เชน ถา method ใน class แมมีนโยบายการเขา หาทเ่ี ปน public ในclass ลกู ก็ไมสามารถทจ่ี ะเปลยี่ นใหเ ปน private ไดเพราะการเขา หาแบบ private นน้ั เขมงวดมากกวาแตถา ใน class แมน โยบายเปน private เราสามารถทจ่ี ะเปลยี่ นใหเปน public ได พดู งา ย ๆ ก็คอื วา เราเพิ่มความเขมงวดนโยบายการเขาหาใน class ลูกไมได แตลดลงไดเรามาลองดตู ัวอยา งของการถา ยทอดคณุ สมบัตกิ ันอีกสักตวั อยางหน่งึ สมมตวิ า เรามี class ตา ง ๆ ดงั ที่แสดงใน diagram นี้ ภาควิชาคอมพิวเตอรธ ุรกิจ วิทยาลัยฟารอีสเทอรน
บทท่ี 6 การสราง class ใหมจาก class เดมิ และ การถายทอดคุณสมบตั ิ 173เรมิ่ ตนกบั Java Shapes Polygons CircleTriangle Rectangle Squareภาพท่ี 6.2 ตวั อยา ง class ที่เก่ียวของกบั shape ตา ง ๆโดยกาํ หนดใหก ารถา ยทอดคณุ สมบัตเิ ปนไปดงั ทเ่ี หน็ ใน diagram คอื Shapes เปน base classPolygons และ Circle เปน class ลกู ของ Shapes สว น Triangle Rectangle และ Square เกิดมาจากclass Polygonsในทกุ ๆ class เรากาํ หนดใหม ี method what() เพยี ง method เดียว ดงั ทแ่ี สดงไวใ น code ทีเ่ หน็ นี้//Shapes.java - Base class for all shapesclass Shapes { //self info. protected String what() { return \"I am a shape\";}//Polygons.java – Polygonclass Polygons extends Shapes { //self info. protected String what() { return \"I am a polygon.\"; }}//Circle.java - sub-class of Shapesclass Circle extends Shapes { //self info protected String what() { return \"I am a circle.\"; }}//Triangle.java - sub-class of Polygonsclass Triangle extends Polygons { //self info. protected String what() { return \"I am a triangle.\"; }}//Square.java - sub-class of Polygons ภาควิชาคอมพิวเตอรธ รุ กิจ วิทยาลยั ฟารอ สี เทอรน
บทท่ี 6 การสรา ง class ใหมจาก class เดมิ และ การถา ยทอดคุณสมบัติ 174เร่ิมตนกบั Javaclass Square extends Polygons { //self info. protected String what() { return \"I am a square.\"; }}//Rectangle.java - sub-class of Polygonsclass Rectangle extends Polygons { //self info. protected String what() { return \"I am a rectangle.\"; }}เราเขยี นกําหนดใหโปรแกรมตรวจสอบเปนดังน้ี//TestShapes.java - driver programclass TestShapes { public static void main(String[] args) { //creating different shape objects from Shapes Shapes shape = new Shapes(); Shapes poly = new Polygons(); Shapes sq = new Square(); Shapes cir = new Circle(); //display info. about particular shapes System.out.println(shape.what()); System.out.println(sq.what()); System.out.println(cir.what()); System.out.println(poly.what()); }}ในโปรแกรมตรวจสอบเราไดสราง object สต่ี วั จาก class Shapes แตท าํ การกําหนดการสรา งผา นทางconstructor ของ class น้นั ๆ ทีเ่ ราตอ งการสราง เชนShapes sq = new Square();ถา มองดอู ยา งผิวเผนิ จะเห็นวา การประกาศแบบนไ้ี มน า ทจ่ี ะทําได เนอ่ื งจากวา เรากาํ หนดให sq เปนobject ท่มี สี ถานะเปน Shapes แตกลับไปเรียก constructor ของ Square แต Java ยอมใหการสรา งobject แบบนี้เกิดขน้ึ ไดก็เพราะวา Square เปน class ทเี่ กดิ มาจาก class Shapes (พูดงาย ๆ ก็คอื Circleเปน Shapes แบบหน่ึง) และภายใน class Shapes เรากาํ หนดใหมี method what() อยู ดงั นน้ั class ลกูที่เกิดมากส็ ามารถทีจ่ ะเขาหา method นี้ไดแ ต ภายในตวั class ลูกท้ังหมดกม็ ี method what() อยดู ังนัน้การเรียก method what() ขึน้ มาใชจ ึงเปน การเรยี ก method ทีม่ ีอยภู ายใน class ลูก (overriding) ดงั ท่ีแสดงใหเ หน็ จากผลลพั ธน ี้I am a shapeI am a square.I am a circle.I am a polygon. ภาควิชาคอมพิวเตอรธุรกจิ วทิ ยาลยั ฟารอสี เทอรน
บทที่ 6 การสรา ง class ใหมจ าก class เดมิ และ การถา ยทอดคุณสมบัติ 175เริม่ ตน กบั JavaPolymorphism (ความมีรปู แบบทหี่ ลากหลาย)การทํางานในลกั ษณะที่ไดกลา วมาน้ันเราเรยี กวา late binding หรอื ท่เี รยี กกันมากมายในหนังสือหลาย ๆเลมวา polymorphism ซง่ึ หมายถึงความเปลย่ี นแปลงรปู แบบตามสภาพของ object ที่ไดถ กู สรา งขนึ้ หรอืที่เปน อยู คําวา late binding หมายถึงเวลาท่ี compiler จัดสรรหนวยความจําใหก บั ตวั แปรในขณะท่ีโปรแกรมกําลงั ถกู execute (run อยู) ไมใชใ นขณะทก่ี าํ ลัง compile โปรแกรมPolymorphism ทําไดเ ฉพาะ method เทา น้ันเราไมส ามารถจะใชว ธิ กี ารแบบนกี้ บั ตวั แปรท่อี ยใู น classได การเขา หาตวั แปรจะตอ งทาํ ผา นทาง object ที่เกิดจาก class นนั้ ๆ เทาน้นัสมมตวิ า เราตอ งการทจ่ี ะเขยี น method ท่คี าํ นวณหาเสน รอบวงของ object ตา ง ๆ ทสี่ รา งข้ึนมาจากclass Shapes เราก็อาจทาํ ไดด วยการเขียน method ลงไปใน class นั้น ๆ (ทถ่ี กู สรา งมาจาก class แม)แตการกระทาํ ดงั กลาวคงไมคอยดีเทา ไรนกั ถา เราไมร วู า object ที่เราตอ งการสรา งขน้ึ มานน้ั รปู รา งหนาตาเปน อยา งไร และคงจะไมคอยเขาทา เทา ไรนกั ทีจ่ ะหาเสน รอบวงของ shape ท่ีเรายังไมรูวา เปน shapeอะไร แต Java เอ้อื โอกาสใหเ ราสามารถทีจ่ ะประกาศ (declare) method ใน class แมแตไปกาํ หนดหนาที่ (define) ใน class ลกู วิธีการดงั กลาวเราเรยี กวา การสราง abstract classAbstract class เปน class ท่ีมกี ารประกาศ method ใน class แม แตไมม กี ารกาํ หนดหนา ที่ใด ๆ เรอ่ื งของการกําหนดหนา ท่จี ะเปน ภาระของ class ลูก ดงั เชน ตัวอยางตอไปนี้//Shapes.java - Base class for all shapespublic abstract class Shapes { private String iAm; Shapes(String whatIam) { iAm = new String(whatIam); } //self info. public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(\"I am a \" + iAm); return new String(buffer); } //dummy method - implementation is done in derived classes //to calculate a perimeter of a shape public abstract double perimeter();}เราเปลี่ยนแปลง class Shapes ของเราใหเปน abstract class พรอ มทงั้ ประกาศ method perimeter() ที่ไมมี code ใด ๆ อยูเลย หลังจากน้นั เราก็สรา ง class อืน่ ๆ ท่ีไดรบั การถา ยทอดคณุ สมบตั จิ าก classShapes ดงั น้ี//Polygons.java – Polygonpublic abstract class Polygons extends Shapes { //constructor Polygons(String type) { super(type); } //self info. public String toString() { return super.toString(); ภาควิชาคอมพิวเตอรธ รุ กิจ วทิ ยาลัยฟารอ สี เทอรน
บทที่ 6 การสราง class ใหมจ าก class เดิม และ การถา ยทอดคุณสมบตั ิ 176เริม่ ตน กบั Java} //dummy method to be implemented by derived classes public abstract double perimeter();}//Triangle.java - sub-class of Polygonspublic class Triangle extends Polygons { private double side1, side2, side3;//constructorTriangle(String type, double side1, double side2, double side3) { super(type); //calling base-class constructor this.side1 = side1; this.side2 = side2; this.side3 = side3;}//self info.public String toString() { return super.toString();} //calculating a perimeter of this triangle public double perimeter() { return side1 + side2+ side3; }}//Circle.java - sub-class of Shapespublic class Circle extends Shapes { private double radius;//constructorCircle(String type, double radius) { super(type); this.radius = radius;}//self infopublic String toString() { return super.toString();} //calculating a perimeter of this circle public double perimeter() { return 2.0 * Math.PI * radius; }}//Square.java - sub-class of Polygonspublic class Square extends Polygons { double side;//constructor ภาควิชาคอมพิวเตอรธุรกิจ วทิ ยาลัยฟารอีสเทอรน
บทท่ี 6 การสรา ง class ใหมจ าก class เดิม และ การถา ยทอดคุณสมบตั ิ 177เริ่มตนกับ Java Square(String type, double side) { super(type); this.side = side; } //self info. public String toString() { return super.toString(); } //calculating a perimeter of this square public double perimeter() { return side * 4; }}หลังจากทีเ่ ราไดส ราง class Polygons class Circle class Triangle และ class Square พรอ มทง้ั กําหนดหนา ท่ขี อง method perimeter() ใน class Circle class Triangle และ class Square เรยี บรอ ยแลว เราก็เขียนโปรแกรมเพื่อตรวจสอบวา method ของเราใชง านไดถ กู ตองหรอื ไม ดงั น้ี//TestShapes.java - driver programclass TestShapes { public static void main(String[] args) { Shapes cir, tri; Polygons sq; //instantiate shapes sq = new Square(\"square\", 4.0); cir = new Circle(\"circle\", 2.0); tri = new Triangle(\"triangle\", 3.0, 4.0, 5.0); //display info. about particular shapes System.out.println(sq + \" with a perimeter of: \" + sq.perimeter()); System.out.println(cir + \" with a perimeter of: \" + cir.perimeter()); System.out.println(tri + \" with a perimeter of: \" + tri.perimeter()); }}ในโปรแกรม TestShapes.java เราประกาศตวั แปร cir และ tri จาก class Shapes ตวั แปร sq จาก classPolygons สาเหตทุ เ่ี ราประกาศตัวแปรแทนการสราง object กเ็ พราะวา Java ไมยอมใหเ ราทําเนอ่ื งจากวา class Shapes และ class Polygons เปน class ที่ถกู กาํ หนดใหเปน abstract class แตเราสามารถทีจ่ ะใชต ัวแปรทัง้ สามในการสรา ง object (instantiation) จาก class Circle class Square และclass Triangle ไดประโยคในการสราง object ทงั้ สามsq = new Square(\"square\", 4.0);cir = new Circle(\"circle\", 2.0);tri = new Triangle(\"triangle\", 3.0, 4.0, 5.0);อาจดูแปลกไปจากการสรา ง object ทเ่ี ราไดเ คยทาํ มา แตเราสามารถทาํ ไดก ็เพราะวา class Shapes เปนbase class ของ class ท้ังหมด สวน class Polygons ก็เปน base class ของ class Square และ class ภาควิชาคอมพิวเตอรธุรกจิ วทิ ยาลยั ฟารอสี เทอรน
บทท่ี 6 การสราง class ใหมจาก class เดิม และ การถายทอดคุณสมบตั ิ 178เริม่ ตนกบั JavaTriangle การสรา ง object ท้งั สามจึงสามารถทําได พดู งาย ๆ ก็คอื วา ทั้ง sq cir และ tri ตางก็เปนshape ทงั้ น้ัน (e.g. a square is a shape, a circle is a shape, a triangle is a shape etc.)ผลลพั ธท เ่ี ราไดจากการ run คือI am a square with a perimeter of: 16.0I am a circle with a perimeter of: 12.566370614359172I am a triangle with a perimeter of: 12.0Polymorphism มปี ระโยชนม ากในการกาํ หนดหนา ที่ของ method ที่ object ตา ง ๆ ใชรว มกนั ซึง่ หนา ที่ตาง ๆ เหลานจี้ ะข้ึนอยูกับคุณลกั ษณะของ object ทเี่ กดิ จาก class น้ัน ๆ ดังท่ีเราไดแสดงใหดูในการหาเสนรอบวงของรูปทรงตาง ๆ หากเราตอ งการเรากส็ ามารถทจ่ี ะสรา ง array ในการเก็บ shape ตาง ๆเหลาน้ีได ดังตวั อยางทแ่ี สดงใหเหน็ น้ี//TestShapes.java - driver programclass TestShapes { public static void main(String[] args) { Shapes []shapes = new Shapes[5]; //instantiate 5 shapes for(int i = 0; i < 5; i++) shapes[i] = randomShape(); //display info. about particular shapes for(int i = 0; i < 5; i++) { System.out.print(shapes[i] + \" with a perimeter of: \"); System.out.println(shapes[i].perimeter()); } } public static Shapes randomShape() { switch((int)(Math.random() * 3)) { default: case 0: return new Circle(\"circle\", Math.random() * 12.0); case 1: return new Square(\"square\", Math.random() * 10.5); case 2: return new Triangle(\"triangle\", 2.5, 4.0, 5.5); } }}เราเลอื กที่จะใหการสรา งรูปทรงตา ง ๆ เกิดแบบ random ดังนัน้ เราจึงเขียน method randomShape()ข้ึนมาใชส ําหรบั การสรางรูปทรงท่ีไมมขี อ กําหนดท่ีตายตวั รปู ทรงทเ่ี กดิ ข้นึ จะถกู กําหนดโดย methodrandom() ของ class Mathผลลัพธท ่ีไดจ ากการ run คอืI am a square with a perimeter of: 15.282560130191253I am a triangle with a perimeter of: 12.0I am a circle with a perimeter of: 0.209235603993188I am a triangle with a perimeter of: 12.0I am a circle with a perimeter of: 7.8292546239806695หากเราอยากรวู า object ทส่ี รา งขน้ึ มานน้ั เกิดจาก class อะไรเรากส็ ามารถหาไดจ ากการใช methodgetClass() และ method getName() ทม่ี ีอยใู น class Class ของ Java เชน ถาเราตอ งการรูวา object ท่ีshapes[0] เกบ็ ไวเ กดิ มาจาก class อะไรเรากใ็ ชคําส่ังดงั น้ี ภาควิชาคอมพิวเตอรธ รุ กิจ วิทยาลยั ฟารอสี เทอรน
บทที่ 6 การสรา ง class ใหมจาก class เดิม และ การถายทอดคุณสมบัติ 179เร่มิ ตน กบั JavaClass object = shapes[0].getClass();System.out.println(object.getName());ถาเราอยากรูวา object ตัวนี้มี class แมห รอื ไมเรากใ็ ช method getSuperclass() เชนClass shape = object.getSuperclass();System.out.println(shape.getName());ยงั มี method ใน class Class อกี หลายตวั ทเ่ี ราสามารถนาํ มาใชได แตโดยสว นใหญแ ลว เราแทบท่ีจะไมตอ งใช method เหลาน้ใี นการพฒั นาโปรแกรมทว่ั ไปเลย เพราะ method เหลานจี้ ะใหข อ มูลท่เี กี่ยวกับclass ท่ผี ูใช (หรอื ของ Java) สรางขน้ึ มาเทา น้นั เองการสง และรบั objectตวั อยา งตอไปน้เี ปนการสง object เขาไปใน method พรอมกบั การสง object กลับดวยการเปล่ยี นแปลงบางอยาง สมมติวาเราตองการสรา ง วงกลมจาก สเี่ หลี่ยมดา นเทาที่มีอยแู ลว เรากอ็ าจเขียน method ท่ีทาํ หนา ทน่ี ใ้ี หเรา ดงั นี้//SquareToCircle.java - Passing and returning object to/from methodclass SquareToCircle { public static void main(String []args) { Shapes square; //a square object Shapes circle; //a circle object //creating a square with side = 3 square = new Square(\"square\", 3.0); System.out.println(square + \" with an area of \" + square.area()); //creating a circle from a square circle = SqToCir(square); System.out.println(circle + \" with an area of \" + circle.area()); } //method to convert a square to a circle public static Shapes SqToCir(Shapes square) { //finding a radius from an area of a square double SqArea = square.area(); double radius = Math.sqrt(SqArea / Math.PI); //instantiating a circle Circle circle = new Circle(\"circle\", radius); return circle; }}เพื่อใหการทาํ งานของเราประสพผลสาํ เรจ็ เราไดเ พม่ิ abstract method area() ใน class Shapes และclass Polygons และทาํ การกาํ หนดหนา ที่ของ method area() ใน class Square และ class Circle ซงึ่เปน การคํานวณหาพืน้ ทข่ี องรปู ทรงทีไ่ ดถ ูกสรา งขน้ึใน class Shapes เรากาํ หนด ดังนี้ (ใน class Polygons กท็ าํ แบบเดียวกนั )public abstract class Shapes { … ภาควิชาคอมพิวเตอรธ ุรกิจ วิทยาลยั ฟารอสี เทอรน
บทที่ 6 การสรา ง class ใหมจ าก class เดิม และ การถา ยทอดคุณสมบตั ิ 180เร่ิมตน กบั Java … //code อน่ื ๆ เหมอื นเดิม … … public abstract double perimeter(); public abstract double area();}ใน class Circle เรากาํ หนด code ของ method area() ดงั น้ี//calculate area of this circlepublic double area() { return Math.PI * radius * radius;}และใน class Square เรากาํ หนด code ของ method area() ดังน้ี//calculate area of this squarepublic double area() { return side * side;}ในตัวโปรแกรมของเรา เราสรา ง object สองตวั คือ square และ circle โดยกําหนดให square มีความยาวของดานแตละดา นเทากบั 3.0 หลงั จากทแี่ สดงขอมลู ของ square เรียบรอยแลว เรากส็ ง square ไปให method SqToCir() ซ่งึ เปน method ท่ีทาํ การเปลย่ี น square ใหเปน circle โดยกําหนดใหท ง้ั สองobject มพี ื้นท่เี ทากนัpublic static Shapes SqToCir(Shapes square) { //finding a radius from an area of a square double SqArea = square.area(); double radius = Math.sqrt(SqArea / Math.PI); //instantiating a circle Circle circle = new Circle(\"circle\", radius); return circle;}เราเริ่มตน ดวยการหาพืน้ ที่ของ square ทส่ี งเขามา หลังจากนน้ั เราก็หารศั มขี องวงกลมทเ่ี ราตอ งการสรางจากพน้ื ท่ี ท่ีหาได เมือ่ ไดแลวเราก็สรา ง circle ดว ยรัศมีน้ี เสรจ็ แลว จึงสง วงกลมท่ไี ดนีก้ ลับไปผลลัพธท ีเ่ ราไดจากการ run โปรแกรมของเราคอืI am a square with an area of 9.0I am a circle with an area of 9.0ขอดีของการกาํ หนดให base class เปน abstract class นั้น กค็ อื เราไมตองกําหนดหนาทขี่ อง methodใน class แม เพราะวา เราอาจไมร ขู อ มลู ทงั้ หมดที่ method ตองการใช ดังเชน method perimeter() และmethod area() เนอื่ งจากวา เรายังไมร ูว า shape ทมี่ ีอยเู ปน object ชนดิ อะไร ขอมูลเปน อยางไร แตเ รารูขอมลู ทั้งหมดท่ี Circle และ Square ตอ งการใชในการคํานวณหาเสนรอบวง และพน้ื ทจี่ าก การสรางobject ของ class ทั้งสอง ภาควิชาคอมพิวเตอรธรุ กจิ วทิ ยาลยั ฟารอ สี เทอรน
บทท่ี 6 การสรา ง class ใหมจาก class เดมิ และ การถายทอดคุณสมบตั ิ 181เร่ิมตน กบั Javaการสรา ง Interfaceจากเทคนคิ การใช polymorphism ในตวั อยางกอ นหนา นี้ เราตองกําหนดใหม ี method ใน class แม และไปกาํ หนดหนาที่ของ method เหลา นใี้ น class ลกู ซึง่ เปน การสรา ง class ในลักษณะที่ซ้ําซอ นพอสมควรถาเราตอ งคณุ สมบัติของ polymorphism ใน class ทีเ่ กดิ จาก class แมนี้ เราก็ไมจําเปนทจ่ี ะตองสรางclass แมข้นึ มา แตไปสรา ง interface ขึน้ มาแทนInterface เปนที่รวบรวมคาคงที่ และ abstract method ตาง ๆ ท่จี ะตอ งมกี ารเรียกใชใ น class อนื่ ๆ ท่ีเรยี ก interface น้ไี ปใช การสรา ง interface กไ็ มย าก แทนทีเ่ ราจะใชค าํ วา class เรากใ็ ชคําวา interfaceแทน เราจะใช class ตาง ๆ ทเ่ี ราไดสรางไวก อ นหนา น้ีในเรอ่ื งของรูปทรงตา ง ๆ เปนตัวอยา ง และเราจะตอ งทําการเปลย่ี นแปลง class ตาง ๆ ดงั น้ีใน class Shapes และ class Polygons เราจะตัดเอา abstract method perimeter() และ area() ออกพรอมกบั เปลีย่ นการประกาศ class Shapes ใหเปนดงั น้ีpublic abstract class Shapes implements Calculate { private String iAm; Shapes(String whatIam) { iAm = new String(whatIam); } //self info. public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append(\"I am a \" + iAm); return new String(buffer); }}เราเพม่ิ คําวา implements Calculate เขาสดู านหลังสุดของ class Shapes โดยมีเงอ่ื นไขวา เราตองมีinterface ช่อื Calculate อยแู ลว การสรา ง interface กท็ ําไดไ มย าก เราเพยี งแตก าํ หนดให Calculateเปนชอ่ื ของ interface ทเี่ ราตอ งการใช พรอ มทัง้ กาํ หนดใหม ี method ตา ง ๆ ทีเ่ ราตองการทจ่ี ะใหม ีในclass อน่ื ๆ เชน//interface for Shapespublic interface Calculate { double perimeter(); double area();}ในการเขยี น Method ทอี่ ยูใ น interface นั้นเราไมจําเปน ท่ีจะตอ งกาํ หนดนโยบายของการเขา หา การกาํ หนดนโยบายจะตอ งทาํ ใน class ท่เี รียกใช (implement) interface นี้class อืน่ ๆ ท่เี หลอื อยกู ็ไมมกี ารเปลี่ยนแปลงอะไรมากมาย ยกเวน การคํานวณหาพนื้ ท่ีของรูปทรงตา ง ๆใน class Triangle เราเพม่ิ method//calculating an area of this triangle//using Huron's formulapublic double area() { double s = perimeter() / 2.0; double area = Math.sqrt((s * (s-side1) * (s-side2) * (s-side3))); return area;} ภาควิชาคอมพิวเตอรธ รุ กิจ วทิ ยาลยั ฟารอีสเทอรน
บทที่ 6 การสราง class ใหมจาก class เดิม และ การถา ยทอดคุณสมบัติ 182เรม่ิ ตนกับ Javaใน class Circle เราเพมิ่ method//calculate area of this circlepublic double area() { return Math.PI * radius * radius;}ใน class Square เราเพมิ่ method//calculate area of this squarepublic double area() { return side * side;}หลังจากท่ีเปลยี่ นแปลง code บางสวนในโปรแกรมทดสอบ ดังน้ี//TestShapes.java - driver programimport java.text.DecimalFormat;class TestShapes { public static void main(String[] args) { Shapes []shapes = new Shapes[5]; //instantiate 5 shapes for(int i = 0; i < 5; i++) shapes[i] = randomShape(); //display info. about particular shapes DecimalFormat f = new DecimalFormat(\"0.00\"); for(int i = 0; i < 5; i++) { System.out.print(shapes[i] + \" perimeter = \"); System.out.print(f.format(shapes[i].perimeter())); System.out.println(\" area = \" + f.format(shapes[i].area())); } } public static Shapes randomShape() { switch((int)(Math.random() * 3)) { default: case 0: return new Circle(\"circle\", Math.random() * 12.0); case 1: return new Square(\"square\", Math.random() * 10.0); case 2: return new Triangle(\"triangle\", 4.0, 5.0, 6.0); } }}ผลลพั ธท ไี่ ดค อืI am a triangle perimeter = 15.0 area = 9.90I am a square perimeter = 10.32 area = 6066I am a circle perimeter = 45.32 area = 163.46I am a triangle perimeter = 15.00 area = 9.92I am a circle perimeter = 6.76 area = 3.64 ภาควิชาคอมพิวเตอรธรุ กิจ วิทยาลยั ฟารอ ีสเทอรน
บทที่ 6 การสรา ง class ใหมจ าก class เดิม และ การถา ยทอดคุณสมบัติ 183เริ่มตน กบั Javaเนื่องจากวา เราไดทาํ การเรยี กใช interface Calculate ใน class แม ดงั นน้ั เราไมจ าํ เปน ทีจ่ ะตองเรียกใชinterface Calculate ใน class ลูกเพราะ class ลกู เหลา น้ีไดรบั การถา ยทอดคณุ สมบตั จิ าก class แมเรยี บรอ ยแลว เหตผุ ลอีกอยางหน่ึงทีเ่ รากาํ หนดให class Shapes มกี าร implements Calculate กค็ อื เราไมตอ งการเปลย่ี นแปลง code ที่เราไดเขยี นข้ึนกอนหนานม้ี ากมายนักเรามาลองดตู ัวอยางของการใช interface ที่ Java มใี หส ักตวั อยา งหน่งึ โดยเราจะเรียกใช interfaceActionListener ในการตรวจจบั เหตุการณท ีจ่ ะเกดิ ขน้ึ จากตัวโปรแกรม ตัวอยา งน้อี าจมขี อ มลู ทเี่ รายังไมไ ดพดู ถงึ มากพอสมควร แตป ระเดน็ หลกั ทตี่ อ งการแสดงกค็ อื การเรยี กใช interface เราจะปรบั ปรุงโปรแกรมInterests.java ท่ีเราไดเขียนขึ้นในบททส่ี าม ซ่งึ เปนโปรแกรมสําหรบั การคาํ นวณหาดอกเบี้ยทบตน เราจะสรา ง class ข้นึ ใหมด ังน้ีclass Account ใชเ ปนการเก็บ balance คํานวณดอกเบ้ยี แสดงผล class น้ีเรียกใช interface BankRateclass Timer เปน class ท่มี ีอยใู น Java ใชส าํ หรับการกระทาํ ทีต่ องใชเวลาclass Interests1 เปนโปรแกรมทดสอบสว นตา ง ๆ ทเี่ ราสรางขึน้interface BankRate ใชเ ก็บคา คงที่ RATE ทใี่ ชในการคาํ นวณหาดอกเบีย้interface ActionListener ใชใ นการตรวจสอบเหตุการณท เ่ี กดิ จากผใู ชโ ปรแกรม เชน ออกจากโปรแกรมเรากําหนดใหความสัมพนั ธข อง class เปน ไปตาม diagram ที่เห็นนี้ Account GetInterest BankRate ActionListener interface Timerภาพที่ 6.2 การเรยี กใช interfaceเราเริ่มตน ดวย interface BankRate และ class Account//interface for bank ratepublic interface BankRate { double RATE = 5.0;}//Account.javapublic class Account implements BankRate { private double balance; //constructor - initializing balance Account(double balance) { this.balance = balance; } //method to get balance protected double getBalance() { return balance; } //method to deposit ภาควิชาคอมพิวเตอรธ รุ กจิ วิทยาลยั ฟารอ สี เทอรน
บทท่ี 6 การสราง class ใหมจาก class เดิม และ การถายทอดคุณสมบตั ิ 184เริ่มตน กบั Java protected void deposit(double amount) { balance += amount; } //method to calculate interest protected double interest() { return balance * RATE / 100.0; } //method to display info. about this account public String toString() { return \"Balance = \" + getBalance(); }}เราเขียน class Account อยางงา ย ๆ โดยกาํ หนดใหม ี method สําหรบั การกาํ หนด balance การคาํ นวณหาดอกเบ้ยี และการแสดงผลผานทาง method toString() ตอไปเราจะมาดู class Interests1 ซึ่งเปน โปรแกรมทดสอบการใชงานของ class และ interface//Interests1.javaimport java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JOptionPane;import javax.swing.Timer;class Interests1 { public static void main(String[] args) { //create account with initial balance of 1000 final Account acc = new Account(1000); //inner class performing interest calculation //and listening to event from user //stop performing when user hit stop button in //the dialog window class GetInterest implements ActionListener { public void actionPerformed(ActionEvent event) { double ints = acc.interest(); acc.deposit(ints); System.out.println(acc); } } //create object from class GetInterest GetInterest intsPeek = new GetInterest(); //set performing time interval to one second final int DELAY = 1000; //calling actionPerformed() every 1000 milliseconds Timer t = new Timer(DELAY, intsPeek); //start the timer t.start(); //display dialog window - stop performing and exit //program when user hit the button JOptionPane.showMessageDialog(null, \"Stop?\"); System.exit(0); }} ภาควิชาคอมพิวเตอรธรุ กิจ วิทยาลยั ฟารอ สี เทอรน
บทที่ 6 การสราง class ใหมจ าก class เดมิ และ การถา ยทอดคุณสมบตั ิ 185เริม่ ตนกบั Javaในโปรแกรม Interests1.java เราสรา ง object acc จาก class Account ดวยคา balance เร่ิมตนท่ี 1000ภายใน method main() เราสราง class GetInterest ท่เี รยี กใช interface ActionListener ของ Java ซงึ่จะคอยตรวจสอบเหตกุ ารณ (event) ทีอ่ าจเกิดขน้ึ จาก user พรอ มทั้งการคาํ นวณหาดอกเบ้ียmethod actionPerformed() จะถกู เรียกโดย object intsPeek จาก class Timer ดว ยคา delay 1 วนิ าทีดว ยประโยคน้ีTimer t = new Timer(DELAY, intsPeek);แตกระบวนการท้ังหมดจะเรมิ่ ไดด วยการเรยี ก method start() ของ class Timer ดงั น้ี t.start()โปรแกรมของเราจะคาํ นวณหาดอกเบ้ยี ไปจนกวา user จะกดปมุ OK ท่ีแสดงไวใน dialog window ที่ปรากฏอยใู นหนา จอ ซง่ึ dialog window น้ีถกู สรางข้นึ มาดวยคําสงั่JOptionPane.showMessageDialog(null, \"Stop?\");ซึง่ มหี นา ตาดงั น้ีเมือ่ user กดปมุ OK เรากจ็ ะยตุ โิ ปรแกรม และออกจากระบบดว ยคําสงั่ System.exit(0);ตวั อยา งผลลัพธทีไ่ ดจ ากการ run โปรแกรมในชว งเวลาหนง่ึ กอนการกดปมุ คือBalance = 1050.0Balance = 1102.5Balance = 1157.625Balance = 1215.50625Balance = 1276.2815624999998Balance = 1340.0956406249998Balance = 1407.1004226562497Balance = 1477.4554437890622Balance = 1551.3282159785153Balance = 1628.894626777441Balance = 1710.3393581163132Balance = 1795.8563260221288Balance = 1885.649142323235Balance = 1979.931599439397เราตองการท่จี ะแสดงใหเ ห็นถงึ การใช interface ทั้งท่มี อี ยใู น Java และที่เขยี นขึ้นเอง สว นการใชสว นประกอบอื่น ๆ ท่ี Java มใี หเปนเพยี งสงิ่ ทีผ่ ูอานจะไดส มั ผสั ในโอกาสตอไปเรามีทางเลือกสองทางในการสราง และกาํ หนดหนาที่ของ method ดงั ทีเ่ ราไดพ ดู ไว คอื1. กําหนดให class แมเ ปน abstract class พรอมท้งั กําหนดใหม ี ชื่อของ method ทต่ี อ งการ การ กําหนดหนาทข่ี อง method จะเปนภาระของ class ลูกเอง ภาควิชาคอมพิวเตอรธรุ กิจ วิทยาลัยฟารอ ีสเทอรน
บทท่ี 6 การสรา ง class ใหมจ าก class เดมิ และ การถา ยทอดคุณสมบัติ 186เริม่ ตน กบั Java2. กาํ หนดให class เรียกใช interface ท่ีมกี ารกาํ หนดชอื่ ของ method และ class ตองกาํ หนดหนาที่ ของ method น้นั เองสรปุเราไดพ ดู ถึงการสราง class ใหมจ าก class ทมี่ ีอยกู อนแลว การถายทอดคณุ สมบัติจาก class แมสู classลกู การ override method การใช polymorphism การสรา งและใช interface โดยสรุปแลว สง่ิ สําคญั ท่ีเราไดพ ูดไวค ือ9 เราสามารถสรา ง class ใหมจาก class ทีม่ อี ยกู อ นแลว ดวยการใชคาํ วา extends ซ่งึ class ทีเ่ รา extends มานั้นเราเรยี กวา base class หรือ parent สวน class ทเี่ ราสรา งขึน้ ใหมเราเรยี กวา sub class หรือ child9 เราสรา ง abstract class ดวยการใชค ําวา abstract ซง่ึ ภายใน class ทีเ่ ปน abstract class นั้นจะมี method ประกาศอยู แตหนา ทีข่ อง method ยงั ไมไ ดถ กู กําหนด การกาํ หนดจะทาํ ใน class ลูกเดทา นน้ั และเราไมส ามารถที่จะสรา ง object จาก abstract class ได9 sub class ไมไ ดรับการถายทอด constructor ของ super class9 ถาเรากาํ หนดนโยบายการเขา หาของ method หรอื ตัวแปรใหเปน private ใน class แม class ลูกจะ ไมสามารถเขาหาตวั แปร หรือ method ได9 ตวั แปรที่ประกาศจาก class แมส ามารถทีจ่ ะใชเปนตัวชี้ไปยงั object ของ class ลูกได ซง่ึ ทําใหก าร เรียกใช method ทีอ่ ยูใน class ลกู เปนไปได9 abstract class เปน class ที่ไมตองกําหนดหนา ท่ใี ห method ทุก ๆ ตวั ใน class9 interface ประกอบไปดวย คา คงที่ abstract method และ inner class9 class ทีไ่ มกําหนดหนาทใ่ี หก ับ method ทุกตวั ท่ีตวั มนั เองตอ งใช interface จะตอ งประกาศใหเ ปน abstract classแบบฝก หดั1. จากขอ มูลทใ่ี หเ ปนคูในแตล ะขอ จงแสดงถึงความสัมพันธว าสวนไหนเปน super class และสว นไหน เปน sub classผูจัดการ ลกู จางนักศึกษา อาจารยคน นักศกึ ษาอาจารย บคุ ลากรสามี ภรรยาพอ ลูก2. สมมตวิ า class RumRaisin extends มาจาก class Icecream จงหาวา ประโยคใดตอไปน้ีเปน ประโยคที่ Java ยอมรับRumRaisin scoop1 = new RumRaisin();Icecream scoop2 = new Icecream;scoop2 = scoop1;scoop1 = scoop2;scoop2 = new RumRaisin();scoop1 = new Icecream();3. จงวาด diagram ที่แสดงถึงความสมั พันธข องการถายทอดคณุ สมบตั ขิ อง class ท่ีใหน ี้บคุ ลากรผูจ ัดการนกั ศึกษาอาจารยหอ งเรียนอปุ กรณป ระกอยการเรยี น ภาควิชาคอมพิวเตอรธ ุรกิจ วิทยาลยั ฟารอีสเทอรน
บทท่ี 6 การสรา ง class ใหมจ าก class เดมิ และ การถา ยทอดคุณสมบัติ 187เร่ิมตน กบั Java รองอธิการฝายวิชาการ รองอธิการฝายบริหาร บรรณารักษ เจา หนาทกี่ ารเงนิ หวั หนา ฝา ยการเงิน4. เราไดพูดถึงการใช method clone() ในบททเี่ ราพดู ถงึ เรอื่ ง array จง override method clone() เพอ่ื ทําการสราง object ใหมจาก class Shapes ท่ไี ดกลา วไวใ นบทน้ี5. จงเพมิ่ method withdraw() ทีท่ าํ หนาทีใ่ นการถอนเงินออกจากบัญชี ของ class Account ท่ีได กลาวไวใ นบทน้ี ใหเขยี นโปรแกรมทดสอบ6. จาก class Shapes ในบทนี้ class ทไ่ี มไ ดพดู ถงึ และไมม ีการกาํ หนดหนา ที่ใด ๆ เลย คือ class Rectangle จงเขยี น code ท่ที าํ ให class Rectangle นส้ี มบรณู 7. จงออกแบบ class Student ทเ่ี กบ็ ขอมูลของนกั ศึกษาวทิ ยาลัยแหง หนงึ่ โดยใหม ี sub class ที่มีทงั้ นกั ศกึ ษาระดับปริญญาตรี และระดบั ปรญิ ญาโท รวมไปถงึ นกั ศกึ ษาภาคพิเศษ พรอมท้งั เขียน method ในการกาํ หนด และเขาหาขอมลู เหลา น้ี กาํ หนดใหม ี method toString() ในทกุ class สาํ หรบั การแสดงขอมูลของ object ทเ่ี กดิ จาก class น้ัน ๆ ใหเ ขยี นโปรแกรมทดสอบ8. จงออกแบบ class Employee ที่มี sub class เปน TempEmployee และ RegularEmployee โดย กําหนดใหลูกจา งทกุ คนมี ชือ่ และอตั ราจางงานท่คี ดิ เปน จาํ นวน บาท ตอ ชว่ั โมง จงเขียน method ท่ี ทําการคาํ นวณหาคา จา งของลกู จางทกุ คน โดยกําหนดใหการคิดคาจา งของ TempEmployee ขึน้ อยู กับจํานวนช่วั โมงทที่ ํา หากทาํ เกิน 40 ชว่ั โมงใหคดิ คา จางเพ่มิ เปน หนึ่งเทา ครง่ึ ของอตั ราจางประจาํ ของจาํ นวนชัว่ โมงทที่ ําเกนิ สว นลกู จา งประจํา (RegularEmployee) จะไดค า จา งตามอตั ราทไ่ี ดต กลง ไวลวงหนา โดยไมคาํ นึงถึงจาํ นวนชั่วโมงของงานทท่ี ํา จงใชเ ทคนคิ ของ polymorphism ในการ ออกแบบ ใหเ ขยี นโปรแกรมทดสอบ * class Employee ควรเปน abstract class9. จงปรับปรงุ class Shapes หรอื sub class ทมี่ าจาก Shapes ใหม ี method ในการสราง object จาก class หน่งึ ใหเ ปน object จากอีก class หนึ่ง ดงั เชนทท่ี าํ เปนตัวอยางในการสราง object Circle จาก Square จงเขยี นโปรแกรมทดสอบ ภาควิชาคอมพิวเตอรธ รุ กจิ วิทยาลยั ฟารอ ีสเทอรน
ในบททเี่ จด็ นเ้ี ราจะพูดถงึ การใช และการออกแบบ exception หรือท่เี รยี กวา การควบคุมและดกั จับ errorทอี่ าจเกดิ ขนึ้ ในการ compile และ run โปรแกรมหลงั จากจบบทนี้แลว ผูอา นจะไดทราบถึง o ความหมายของ exception o วธิ กี ารใชแ ละควบคุม exception o การใช throws และ try o การออกแบบ และใช exception ทเ่ี ขยี นข้นึ เองในภาษา Java น้นั exception เปนการบอกถึงส่งิ ผดิ ปรกติทเ่ี กิดขึน้ ในโปรแกรม ซึง่ อาจเปน error หรือเหตุการณท ไ่ี มค อยเขา ทาทตี่ อ งการความดูแลเปนพิเศษ โดยทั่วไปในการเขียนโปรแกรมทด่ี ีนั้น เราจะตอ งตรวจสอบถึงเหตกุ ารณท ่อี าจทําใหโปรแกรมของเราลมเหลวในการทาํ งาน เชน ขอ มูลถกู หารดวยศูนย เขา หาขอ มลู ใน array ดวยการใช index ทไ่ี มมีอยจู รงิ หรือ อา งถึงหนวยความจาํ ท่ีเปน null เปน ตนถงึ แมวา เรามีวิธกี ารตรวจสอบ error ตา ง ๆ เหลา นด้ี ว ยการใช if-else หรือ การตรวจสอบอืน่ ๆ ที่ทําใหโปรแกรมของเราทาํ งานไดร าบร่ืน แตจ ะทําให code ของเราดแู ลว วุนวายเพราะถา มกี ารตรวจสอบ errorมาก code ของเรากจ็ ะดซู ับซอนมากย่ิงขน้ึ แตไ มไ ดหมายความวา เราจะไมต รวจสอบ และดกั จบั errorเหลาน้ี การนาํ เอา exception เขา มาเปน ตวั ชว ยในการตรวจสอบและดักจบั ทาํ ใหเ กิดการแยกสว นของcode ทท่ี ํางานไดร าบรื่น ออกจากสวนของ code ทจี่ ัดการเกีย่ วกบั error ทําใหเราสามารถท่จี ะคนหาสว นของ code ทัง้ สองไดง ายขึ้น ถามีการเปลย่ี นแปลง code ในอนาคต ขอดีอกี อันหนง่ึ ของ exception กค็ อืทําใหการตรวจสอบและดกั จับเปน ไปอยางเฉพาะเจาะจง ตรงกับ error ทเี่ กดิ ขึ้น ทาํ ใหการแกไ ขเปนไปอยา งถกู ตอง และเนอื่ งจากวา error มหี ลากหลายรูปแบบ เราตอ งเขียน code ข้ึนมารองรบั ไมเ ชน นน้ั แลวโปรแกรมของเราก็จะไมผ านการ compileเราไมจ ําเปน ทจ่ี ะตอ งใช exception ในการตรวจสอบและดักจบั error ในโปรแกรมเสมอไป เพราะการใชexception จะเสยี คาใชจายในการประมวลผลมาก ทําใหโ ปรแกรมทาํ งานชา ลง ดงั นนั้ เราจะตอ งตัดสนิ ใจใหด วี า ควรจะใช exception ในกรณไี หน อยา งไร ตัวอยา งของโปรแกรมท่ไี มต องใช exception ก็นา จะเปน การใสข อ มลู นาํ เขาแบบผดิ ๆ ของ user ซง่ึ ถือเปน เร่อื งปกติ ถาเรามวั แตเ สยี เวลาในการดกั จบั ดวยการใช exception แทนการตรวจสอบและดักจบั ทวั่ ไปโปรแกรมของเราก็จะเสยี เวลาในการประมวลผลสวนอน่ื ๆ ไปการใช exception ใน Java นัน้ จะโดยทั่วไปจะเปน การโยน (throw) การจดั การ error ทีเ่ กิดขนึ้ ใหกับสว นของ code ทท่ี าํ หนาท่ีในดา นการจดั การกบั error นั้น ๆ ท่เี กิดข้นึ ซง่ึ code สวนน้จี ะคอยดักจบั(catch) ถา มกี ารโยนเกิดขึน้ แตไ มจ าํ เปน ที่ code สว นน้ีจะตองแกไข error ท่ีเกิดขึน้ อาจเปนเพียงการดกัจบั เทานน้ั เพื่อใหโ ปรแกรมทาํ งานตอไปไดเทา น้ันเราคงไมพดู ถึงขอมูลตา ง ๆ ทเ่ี กี่ยวกบั error และ exception มากนกั แตจะเนนการใช exception ในการตรวจสอบและดกั จับ error แบบพอประมาณ ผทู ส่ี นใจกส็ ามารถที่จะหาอานไดจ ากหนังสอื Java ทัว่ ๆ ไปหรอื ใน web sit ของ Java เองException โดยปกติจะเปน object จาก sub class (class ใด class หนง่ึ ) ของ class Throwable ท่ีJava มีให และ class หลัก ๆ สอง class ทเ่ี กดิ จาก class Throwable โดยตรงท่ีเปน class หลักของclass ทเ่ี ปน class เฉพาะของการจัดการกับ error คอื class Error และ class Exception (ภาพที่ 7.1)
บทท่ี 7 การตรวจสอบและดกั จบั error (Exceptions) 189เร่ิมตน กบั Java Throwable Error Exception Other sub classes Other sub classesภาพที่ 7.1 Class Throwable และ sub classesโดยการออกแบบของ Java เราไมค วรทจ่ี ะ catch error ทเี่ กิดขึน้ จากการตรวจสอบของ class Errorเพราะ error ทเ่ี กิดขน้ึ จะเปน error ท่ี โดยทว่ั ไปจะไมเ กิดขนึ้ (หรอื ไมคาดวาจะเกดิ ) ซ่งึ มอี ยูส าม classคือ ThreadDeath LinkageError และ VirtualMachineError เราคงจะไมเขาไปวนุ วายกับ class ทัง้ สามเพราะวา เราไมส ามารถทจ่ี ะแกไ ข error ท่เี กิดขนึ้ นีไ้ ดโดยตรง และตอ งใชก ารตรวจสอบอยา งละเอยี ดกบัerror ท่เี กิดขึ้น (แตคงตอ งหวงั ในใจวา error ท่วี าคงไมเ กิดขน้ึ กบั เรา)เราจะมาดูตวั อยางการใช exception ในการจดั การกบั error ทเี่ กิดขึ้นในโปรแกรมของเรา ดว ยโปรแกรมตัวอยางตอ ไปน้ี//ThrowException.javaclass ThrowException { public static void main(String[] args) throws Exception { int number = 10; int divider = 0; System.out.println(\"Divide \" + number + \" by \" + divider); int result = number / divider; System.out.println(\"Result is \" + result); }}โปรแกรมตวั อยา งดา นบนนท้ี าํ การ throw exception ซ่งึ เปน exception ทีเ่ กดิ ขนึ้ ในขณะท่ีโปรแกรมกาํ ลงั ไดร บั การประมวลผล (เชน การหารตวั เลขที่เปน int ดว ย 0 – เราตง้ั ใจให error น้ีเกดิ ข้ึน) โปรแกรมตวั อยางของเราไมไ ดทําการดกั จบั ใด ๆ ทาํ แตเ ฉพาะการตรวจสอบ error ท่เี กิดขน้ึ เทา นน้ั ดังที่เหน็ จากผลลพั ธข องการ run น้ีDivide 10 by 0java.lang.ArithmeticException: / by zero at ThrowException.main(ThrowException.java:10)จะเหน็ วา Java จะฟอ งใหเรารวู า error ท่ีเกดิ ขึน้ เปน error ชนดิ ไหน (ArithmeticException) ที่พยายามหาร int ดวย 0 พรอ มกับบอกวาเกิดขึน้ ในบรรทดั ที่เทา ไร หลังจากนน้ั กย็ ตุ กิ ารทาํ งานถา หากวา เราตอ งการทจ่ี ะแกไ ข หรอื ทําการใด ๆ สักอยางหน่ึงกับ error ทเี่ กิดขน้ึ เราตองใช try และcatch ดังตวั อยา งตอไปน้ี ภาควิชาคอมพิวเตอรธรุ กิจ วิทยาลัยฟารอีสเทอรน
บทที่ 7 การตรวจสอบและดกั จับ error (Exceptions) 190เร่มิ ตน กับ Java//TryAndCatchExample1.java//adopted from Ivor Horton'sclass TryAndCatchExample1{ public static void main(String[] args) { int number1 = 15; int number2 = 0; try { System.out.println(\"Try to divide by zero in a try block.\"); int result = number1 / number2; System.out.println(\"Leaving a try block.\"); } catch(ArithmeticException ex) { System.out.println(\"Exception caught in a catch block.\"); } System.out.println(\"After a try block.\"); }}โปรแกรม TryAndCatchExample1.java เปนโปรแกรมตัวอยา งการใช try และ catch ในการจดั การกบัการหาร int ดว ย 0 (เราจะไมใ ชการ throws exception เหมอื นกบั ตัวอยางแรก) เรากําหนดให number1มีคา เปน 15 และ number2 มคี า เปน 0 พรอ มทง้ั กําหนดใหresult = number1 / number2;ใน block ของ try ซง่ึ ประโยคดงั กลาวจะทาํ ใหเ กิดการโยน exception ไปยัง block ของ catch และในblock ของ catch เราจะดักดว ย exception ที่ชื่อ ArithmaticException เราไมไ ดท าํ อะไรมากมายไปกวาการแสดงขอความวา มกี ารดักจบั error ผลลพั ธท ไี่ ดจากการ run คือTry to divide by zero in a try block.Exception caught in a catch block.After a try block.จากผลลัพธท่ไี ด code ทไ่ี ดร บั การประมวลผลคือ ประโยคทอ่ี ยูใ น block ของ try 2 ประโยคแรกโดยเฉพาะประโยคทสี่ อง ท่ีทาํ ใหก ารประมวลกระโดดไปยัง block ของ catch ทําใหป ระโยคทสี่ ามไมไดรบั การประมวลผล และหลังจากที่ประมวลผลประโยคท่ีอยูใน block ของ catch แลว การประมวลผลประโยคสดุ ทายทต่ี ามหลัง block ของ catch จึงเกิดข้นึเราสามารถใช ตัวแปร ex ท่เี ราไดประกาศใน parameter list ของ method catch() แสดงถงึ ขอความที่บงบอกเก่ียวกับ error ทีเ่ กดิ ขึ้น ดว ยการเพม่ิ ประโยคตอไปน้ีใน block ของ catchSystem.out.println(ex.getMessage());ex.printStackTrace();ประโยคแรกเรียกใช method getMessage() ทเ่ี กิดขนึ้ ทาํ การแสดงผลไปยงั หนาจอ สว นประโยคทสี่ องเปนการตรวจสอบถึงทม่ี าของ error ท่เี กิดข้นึ ดังทแ่ี สดงใหเห็นจากการ run โปรแกรมอกี คร้ังหลังจากการเปลย่ี นแปลง code ใน block ของ catchTry to divide by zero in a try block.Exception caught in a catch block./ by zerojava.lang.ArithmeticException: / by zero ภาควิชาคอมพิวเตอรธ ุรกจิ วทิ ยาลยั ฟารอ สี เทอรน
บทท่ี 7 การตรวจสอบและดักจบั error (Exceptions) 191เรม่ิ ตนกับ Javaat TryAndCatchExample1.main(TryAndCatchExample1.java:11)After a try block.เราไมจาํ เปนทจ่ี ะตองแสดงผลท่เี กิดขน้ึ ไปยงั หนาจอ สวนใหญแลว ขอมูลเหลานีจ้ ะเปนประโยชนต อ การตรวจสอบถงึ error ทเ่ี กิดขน้ึ เทานั้นเอง ส่ิงทส่ี ําคญั ที่เราตองกังวลกค็ อื การตรวจสอบและดักจับ error ที่อาจเกิดข้นึJava กาํ หนดให try และ catch เปนของคกู นั เราไมส ามารถทจี่ ะแยก block สองออกจากกนั ได ถา เรากาํ หนดใหม ปี ระโยคอะไรก็ไดส กั ประโยคหนงึ่ ระหวาง block ของ try และ catch โปรแกรมของเราจะcompile ไมผ าน ดงั ตวั อยา งทม่ี ีการเพม่ิ ประโยคระหวา ง block ท้งั สองนี้ … … System.out.println(\"Leaving a try block.\");}System.out.pritnln(\"In between try and catch blocks.\");catch(ArithmeticException ex) { … …ถา เรา compile เราจะได error ดงั ทเี่ หน็ น้ีTryAndCatchExample1.java:9: 'try' without 'catch' or 'finally' try { ^TryAndCatchExample1.java:15: 'catch' without 'try' catch(ArithmeticException ex) { ^2 errorsตัวอยา งการใช try และ catch ที่ classic อกี อันหนึ่งก็คือ การใช try และ catch ใน loop ดังตัวอยางตอไปนี้//TryAndCatchExample2.java//adopted from Ivor Horton'sclass TryAndCatchExample2 { public static void main(String[] args) { int number = 10; for(int index = 5; index >= -1; index--) try { System.out.println(\"try block: index = \" + index); int result = number / index; System.out.println(\"Leaving a try block.\"); } catch(ArithmeticException e) { System.out.println(\"Exception caught in a catch block.\"); System.out.println(e.getMessage()); e.printStackTrace(); } } System.out.println(\"After a try and catch blocks.\");} ภาควิชาคอมพิวเตอรธรุ กิจ วทิ ยาลยั ฟารอ สี เทอรน
บทท่ี 7 การตรวจสอบและดักจบั error (Exceptions) 192เริม่ ตน กับ Javaกอนท่ีจะอธิบายถึงการทาํ งานของตวั โปรแกรม เรามาดผู ลลพั ธท ไี่ ดจ ากการ runtry block: index = 5Leaving a try block.try block: index = 4Leaving a try block.try block: index = 3Leaving a try block.try block: index = 2Leaving a try block.try block: index = 1Leaving a try block.try block: index = 0Exception caught in a catch block./ by zerojava.lang.ArithmeticException: / by zero at TryAndCatchExample2.main(TryAndCatchExample2.java:11)try block: index = -1Leaving a try block.After a try and catch blocks.ประโยคใน block ของ try จะถกู ประมวลผลจนกวา คา ของ index จะเปน 0 จึงจะกระโดดไปประมวลผลประโยคทอี่ ยูใน block ของ catch หลังจากนน้ั ก็กลับไปประมวลผลประโยคที่เหลอื อยใู น block ของ tryและประโยคทอี่ ยทู ายสดุ ในโปรแกรม อกี ประโยคหน่งึจะเหน็ ไดว า เรามที างเลือกอยสู องทางในการจัดการกบั error ทางแรกคอื ยตุ ิการทาํ งาน (terminate)ของโปรแกรม หรอื code สว นนนั้ ๆ ท่ที ําใหเกิด error หรอื ทางท่ีสอง ซึง่ เปนทางเลอื กทที่ าํ ใหโ ปรแกรมหรอื code สว นน้ัน ๆ กลบั ไปรับการประมวลผลใหม (resumption) ทั้งสองวิธีเปน การตรวจสอบและดักจบัerror ทีด่ พี อกัน ทั้งน้กี ็ข้ึนอยกู บั ลักษณะของงานทท่ี าํ อยู ลองมาดตู วั อยา งอีกสักตวั หนึง่ ในการใช classNumberFormatException ในการดักจับ error//NumFormatException.javaimport java.lang.Integer;class NumFormatException { public static void main(String[] args) { int inputNum, sum = 0; //reading input from argument list //only those in [0..9] for(int i = 0; i < args.length; i++) { try { inputNum = Integer.parseInt(args[i]); sum += inputNum; } //ignore input that's not a number catch(NumberFormatException e) { e.printStackTrace(System.out); } } System.out.println(\"Sum is \" + sum); }}เรากําหนดใหโ ปรแกรมของเรารบั ขอมูลจาก command line argument ซึง่ เปน วิธีการทยี่ อมใหผ ใู ชใ สขอมูลตามหลังชือ่ ของโปรแกรม (ดูจากผลลพั ธก าร run) เราจะทาํ การหาผลรวมของตัวเลขเหลา น้ัน ภาควิชาคอมพิวเตอรธ รุ กิจ วิทยาลัยฟารอีสเทอรน
บทที่ 7 การตรวจสอบและดกั จบั error (Exceptions) 193เรมิ่ ตนกับ Javaทงั้ หมดจนกวา ผูใชจ ะพอใจ คอื กดปุม <enter> หลงั จากใสข อ ความจนพอใจ ใน catch block เราดักจบัดวย NumberFormatException ซง่ึ จะไมย อมรบั ขอมลู นาํ เขา ทีไ่ มใชต วั เลขที่เปน int และทุกครัง้ ท่เี จอขอมลู แบบนโ้ี ปรแกรมจะสง รายละเอียดไปใหผ ูใ ช และจะหาผลรวมของขอมูลทถี่ กู ตองน้ัน ดงั ที่แสดงไวดา นลา งน้ี>java NumFormatException 1 2 3 4 p 5 6java.lang.NumberFormatException: For input string: \"p\" atjava.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Integer.parseInt(Integer.java:426) at java.lang.Integer.parseInt(Integer.java:476) at NumFormatException.main(NumFormatException.java:12)Sum is 21ในการสราง block สําหรับการ catch error ทีเ่ กิดข้ึนเราไมจ ําเปน ท่จี ะตอ งมี catch block เพยี ง blockเดียว เราอาจมมี ากกวาหน่ึง catch block ไดแ ตมขี อ แมว า การ catch exception ตองทําจาก sub classออกไปหา super class มฉิ ะนนั้ แลว การดกั จบั ในหลาย ๆ block อาจไมเ กดิ ข้ึน เชนtry { … …}catch(Exception e) { … …}catch(ArithmeticException ex) { … ..}เนอ่ื งจากวา class ArithmeticException เปน class ทีเ่ กดิ มาจาก class Exception ดังนนั้ error ที่เกิดขึน้ กจ็ ะถกู ดักจบั ใน catch block ทัง้ หมด การดักจบั ใน catch block ทส่ี องจึงไมเ กิดข้ึนเรามาลองดตู ัวอยางการดักจบั error ในรปู แบบน้กี ันดู//MultipleCatches.javaclass MultipleCatches { public static void main(String[] args) { //force divide by zero at index = 2 int []number = {1, 2, 0, 4}; int num = 12; //force array index out of bound at index = 4 for(int i = 0; i < number.length + 1; i++) { try { num /= number[i]; System.out.println(\"result = \" + num); } catch(ArithmeticException e) { System.out.println(\"error message: \" + e.getMessage()); e.printStackTrace(); } catch(ArrayIndexOutOfBoundsException e) { ภาควิชาคอมพิวเตอรธุรกิจ วิทยาลัยฟารอ ีสเทอรน
บทที่ 7 การตรวจสอบและดกั จบั error (Exceptions) 194เรมิ่ ตนกับ Java System.out.println(\"error message: \" + e.getMessage()); e.printStackTrace(); } } System.out.println(\"After a for loop.\"); }}เราตองการทจี่ ะบงั คบั ใหเ กิด error สองอยา งคอื หารดวยศนู ย และเขา หา index ของ array ท่ีไมม อี ยูจริง โดยเรากําหนดใหขอ มูลท่ี index = 2 มีคาเปนศนู ย และให for loop ทํางานเกินไปหนง่ึ ครั้ง การ runโปรแกรมตวั อยา งของเราทําใหเกิด ผลลพั ธด งั นีค้ อืresult = 12result = 6error message: / by zerojava.lang.ArithmeticException: / by zero at MultipleCatches.main(MultipleCatches.java:11)result = 1error message: 4java.lang.ArrayIndexOutOfBoundsException: 4 at MultipleCatches.main(MultipleCatches.java:11)After a for loop.จะเห็นวา โปรแกรมของเราดักจับ error ไดตามทเ่ี ราตง้ั ใจไว การหารดวยศนู ย และการอา งถึง index ของarray ท่ีไมมีอยจู ริง ถกู ดกั ไวท ้ังสองตวั ถาเปนการจดั การท่เี ปน การพฒั นาโปรแกรมจริง ๆ เราคงทําแคการดกั จับไมได คงตอ งมกี ระบวนการอ่นื ๆ ในการทาํ ใหโ ปรแกรมทาํ งานไดอ ยางราบรน่ื และกระบวนการจัดการกบั error ที่เกิดขน้ึ ก็ตองมีความซบั ซอ นเพม่ิ ข้ึนJava ยังมี block อีก block หน่ึงทีเ่ อาไว catch error ทีเ่ กิดขนึ้ ทซี่ ่ึงเปน block สุดทา ยของการ catchทงั้ หมด โดยกาํ หนดให block นีท้ ีชอื่ วา finallyFinally เปน การดักจับ error สุดทายของการดักท้งั หมด ดงั น้นั finally จะอยูทอ่ี น่ื ไมไ ดน อกจาก blockสดุ ทายของ catch block ทั้งหมด เราจะแสดงใหด ู ดวยการนาํ เอา finally ไปใสไวเปน block สดุ ทา ยในตัวอยางกอ นหนาน้ี ดังน้ี … …}catch(ArrayIndexOutOfBoundsException e) { System.out.println(\"error message: \" + e.getMessage()); e.printStackTrace();}finally { System.out.println(\"In finally block.\");} … …finally block ทเี่ ราใชจะถกู ประมวลผลเสมอ ไมว า อะไรจะเกิดขึ้นก็ตามใน block อ่นื ๆ กอนหนา ดงัตวั อยา งของผลลพั ธท แี่ สดงใหดบู างสว นนี้ … ภาควิชาคอมพิวเตอรธรุ กจิ วิทยาลยั ฟารอ สี เทอรน
บทที่ 7 การตรวจสอบและดักจับ error (Exceptions) 195เร่มิ ตน กบั Java … at MultipleCatches.main(MultipleCatches.java:13)In finally block.After a for loop.โดยทัว่ ไปหนาท่ีหลกั ของ finally จะเปนการเกบ็ กวาด code ทโี่ ปรแกรมตองการประมวลผล (เชน การปดเปดไฟล) กอ นออกจาก ตวั method main() และกลับออกไปสูร ะบบในท่ีสดุ//ThrowsWithTry.javaimport java.io.*;import java.lang.Integer;class ThrowsWithTry { public static void main(String[] args) throws IOException { BufferedReader buffer; InputStreamReader isr; String input; int first, divider; //keep looping until error occur while(true) { System.out.print(\"Enter a number: \"); isr = new InputStreamReader(System.in); buffer = new BufferedReader(isr); //get first number input = buffer.readLine(); first = Integer.parseInt(input); //get second number System.out.print(\"Enter a divider: \"); input = buffer.readLine(); divider = Integer.parseInt(input); try { double result = first / divider; System.out.println(\"Result = \" + result); } catch(ArithmeticException e) { System.out.println(\"Exception: \" + e.getMessage()); e.printStackTrace(); } } }}โปรแกรม ThrowsWithTry.java เปน โปรแกรมทตี่ อ งการแสดงการใช throws และ try – catch ควบคกู นัโดยตวั โปรแกรมเองจะทาํ การอานขอ มูลสองตัวจาก keyboard ซ่ึงกาํ หนดใหขอมูลทงั้ สองตวั เปน intและจะทาํ การหาผลลัพธของการหารขอมลู ตัวแรก ดว ยขอ มลู ตัวทสี่ องโปรแกรมจะหยดุ การทํางานกต็ อ เมื่อผใู ชใสขอ มูลที่ไมใ ชต วั เลข และจะทาํ การฟอ งถา ขอมลู ตัวทส่ี องของการหารมีคา เปน ศูนย ผลลัพธท ่ีไดจ ากการ run คือEnter a number: 23Enter a divider: 5Result = 4.0Enter a number: 56 ภาควิชาคอมพิวเตอรธุรกจิ วทิ ยาลยั ฟารอสี เทอรน
Search
Read the Text Version
- 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
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246