

จากที่เคยกล่าวแล้วว่าโปรแกรมที่เขียนขึ้นด้วยภาษาจาวา แบ่งออกได้เป็น 2 รูปแบบ คือ java application และ java applet ซึ่งบทที่ผ่านๆมา เราได้ฝึกเขียนโปรแกรมกันไปมากมายหลายโปรแกรมแต่โปรแกรมเหล่านั้นล้วนเป็นโปรแกรมภาษาจาวา ที่เรียก java application ทั้งสิ้น สำหรับบทนี้เราจะมาฝึกเขียนโปรแกรม java applet กัน

แอพเพลต (Applet) หรือจาวาแอพเพลต (java applet) คือโปรแกรมประเภทหนึ่งที่เขียนขึ้นด้วยภาษาจาวา และทำงานอยู่บนโปรแกรมเว็บบราวเซอร์ซึ่งต่างจาก java application ที่สามารถทำงานได้โดยไม่ต้องอาศัยเว็บบราวเซอร์แต่อย่างใด ปกติแล้วแอพเพลตจะถูกเก็บไว้ในเครื่องที่ทำหน้าที่เป็นเว็บเซิร์ฟ (web server) เมื่อใช้เปิดดูเว็บเพจที่มีการเรียกไปยังแอพเพลตนั้น แอพเพลตจึงถูกดาวน์โหลดลงสู่เว็บบราวเซอร์ในเครื่องของผู้ใช้

ข้อดีของแอพเพลตเมื่อเทียบกับ Java application คือ หากเราต้องการเปลี่ยนแปลงแก้ไขการทำงานของโปรแกรม Java applet จะสามารถทำได้สะดวกกว่า Java application เพราะเพียงแค่แก้ไขตัวแอพเพลตที่ถูกเก็บอยู่บนเว็บเซิร์ฟเวอร์เพียงที่เดียว ผู้ใช้งานแก้จะได้ใช้โปรแกรมที่ปรับปรุง (update) ล่าสุดแล้ว ไม่เหมือนกับ Java application ที่หลังจากแก้ไขการทำงานของโปรแกรม เราจะต้องนำโปรแกรมไปติดตั้งลงที่เครื่องของผู้ใช้งานแต่ละเครื่องก่อน ผู้ใช้งานทุกคนจึงจะไดใช้โปรแกรมที่ปรับปรุงล่าสุด
การเรียกการใช้งานแอพเพลตเป็นการเรียนผ่านทางระบบเครือข่าย และแอพเพลตจะมีขนาดไฟล์ที่ค่อนข้างใหญ่เมื่อเทียบกับเว็บเพจทั่วไป ดังนั้นแอพเพลตจึงทำงานได้ดีหากเครื่องของผู้ใช้เชื่อมต่อเข้ากับเครือข่ายที่มีความเร็วในการรับส่งข้อมูลสูง อย่างเช่น ระบบเครือข่ายอินทราเน็ตภายในองค์กรเป็นต้น เพราะจะทำให้แอพเพลตถูกโหลดลงสู่เว็บบราวเซอร์ได้เร็ว ผู้ใช้ไม่ต้องรอนาน

จากที่เคยกล่าวแล้วว่าแอพเพลตถูกเก็บอยู่บนเว็บเซิร์ฟเวอร์ ดังนั้น จึงต้องใช้เวลาพอสมควรในการรอให้แอพเพลตถูกโหลดลงสู่เว็บบราวเซอร์ ซึ่งหากเป็นการเชื่อมต่อเข้าสู่เครือข่ายเพื่อความเร็วในการรับส่งข้อมูลที่ต่ำ อย่างเช่น การเชื่อมต่ออินเทอร์เน็ตด้วยความเร็วต่ำๆแล้ว อาจต้องรอนานกว่าแอพเพลตจะโหลดจนเสร็จสมบูรณ์

แอพเพลตทุกตัวที่เราสร้างขึ้นจะเป็นคลาสลูก (subclass) ของคราส Applet เสมอ หมายถึงเราจะสามารถสร้างแอพเพลตขึ้นมาได้ก็โดยการสืบทอดคุณสมบัติต่างๆมาจากคลาส Applet นั่นเองดังนั้นจึงต้องระบุ extends Applet ต่อท้ายคลาส ที่เราจะสร้างให้เป็นแอพเพลตเสมอ
และเนื่องจากคลาส Applet ถูกเก็บอยู่ในแพ็กเกจ java.applet ดังนั้นจึงต้องอิมพอร์ตคลาสทุกคลาสในแพ็กเกจดังกล่าว ( java.applet.* ) เข้าไว้ในโปรแกรมด้วย
สิ่งสำคัญอีกประการหนึ่ง คือ เราจะต้องกำหนด modifier ของคลาสที่เราสร้างเป็นแอพเพลตให้เป็น Public เสมอด้วย ไม่เช่นนั้นเว็บบราวเซอร์จะไม่สามารถสร้างแอพเพลตให้ทำงานได้
ดังนั้นสรุปแล้วลักษณะโครงสร้างของแอพเพลตจะเป็นดังนี้


คลาส Applet เป็นคลาสที่สืบทอดคุณสมบัติมาจากคลาสอื่นเช่นกัน โดยลำดับขั้นการสืบทอดคุณสมบัติของคลาส Applet เป็นดังนี้


คลาสทุกคลาสในภาษาจาวาล้วนสืบทอดคุณสมบัติของคลาส Object ทั้งสิ้น กรณีที่เราสร้างคลาส ขึ้นโดยไม่ได้ระบุให้สืบทอดคุณสมบัติมาจากคลาสใด คลาสนั่นก็จะรู้ไม่เป็นคลาสลูกของคลาส Object โดยอัตโนมัติ โดยที่เราไม่จำเป็นต้องระบุ extends Object ต่อท้ายคลาสเหมือนอย่างการสืบทอดคุณสมบัติจากคลาสอื่นทั่วไป

คลาส Applet จะสืบทอดคุณสมบัติเกี่ยวกับการวาดรูป ( Drawing ) การทำงานด้านกราฟฟิก และการจัดการกับเหตุการณ์ต่างๆ เช่น การคลิกเมาส์ การกดคีย์บอร์ด เป็นต้น มาจากคลาส AWT Com ponent ( AWT ย่อมาจาก Abstrsct Window Toolkit ) ดังนั้น หากต้องการวาดอะไรก็ตามลงบนแอพเพล ต จะต้องอิมพอร์ตคลาสทุกคลาสในแพคเกจ java. awt เข้าไว้ในโปรแกรมด้วย

แอพเพลตจะไม่มีเมธอด main อย่างเช่น java application แต่แอพเพลตจะประกอบด้วยเมธอดที่สำคัญทั้งหมด 5 เมธอด เพื่อการใช้งานที่แตกต่างกันออกไปดังนี้
เมธอด init() เป็นเมธอดที่ใช้โหลดแอพเพลตเข้าสู่หน่วยความจำ โดยเมธอดนี่จะทำงานครั้งแรกเพียงครั้งเดียวตอนเริ่มต้นการทำงานแอพเลตเท่านั้น
เมธอด start() เป็นเมธอดที่เรียกให้แอพเพลตทำการแสดงผลบนเว็บบราวเซอร์
เมธอด stop() เป็นเมธอดที่เรียกให้แอพเพลตหยุดการทำงาน
เมธอด destroy() เป็นเมธอดที่ทำการรบแอพเพลตออกจากหน่วยความจำ
เมธอด paint() เป็นเมธอดที่แอพเพลตใช้วาดอะไรก็ตามลงบนแอพเพลต

 Initialize stage (คือการทำงานของเมธอด init) เป็นขั้นตอนที่แอพเพลตถูกโหลดเข้าสู่หน่วยความจำ ดังนั้นขั้นตอนนี้จึงเป็นขั้นตอนที่เหมาะสมที่สุดสำหรับการกำหนดค่าเริ่มต้นต่างๆให้กับแอพเพลต
 Start stage (คือการทำงานของเมธอด start) เป็นขั้นตอนที่เรียกให้แอพเพลตแสดงผลบนเว็บบราว เซอร์ เจอกันตอนนี้จะเกิดขึ้นหลังจาก Initialize stage หรือเกิดขึ้นเมื่อผู้ใช้ทำการเปลี่ยนหน้าเว็บเพจไปยังหน้าอื่นแล้ว แต่ได้ย้อนกลับมาเว็บเพจเดิมซึ่งมีแอพเพลตถูกโหลดอยู่ เป็นผลให้แอพเพลตถูกเรียกแสดงผลบนเว็บบราวเซอร์อีกครั้ง (หากสังเกตจะพบว่าขั้นตอนนี้สามารถเกิดได้ตลอดเวลา จะได้ที่แอพเพลตยังคงอยู่ในหน่วยความจำ)
 Paint stag e (คือการทำงานของเมธอด paint) ขั้นตอนนี้จะเกิดขึ้นเมื่อเมื่อมีการว่าอะไร พระรามลงบนแอพเพลต โดยขั้นตอนนี้จะเกิดขึ้นหลัง Start stage เสมอ
 Stop stage (คืนการทำงานของเมธอด Stop) ขั้นตอนนี้จะทำงานเมื่อแอพเพลตไม่อยู่ในสถานะแอคทีฟ (active) เป็นเวลานานๆ เช่น เมื่อผู้ใช้เปลี่ยนหน้าจอไปยังเว็บเพจอื่น (หากสังเกตจะพบว่าขั้นตอนนี้สามารถเปิดได้เสมอตลอดเวลา ตราบใดที่แอพเพลตคงอยู่ในหน่วยความจำโดยจะทำงานสลับกับขั้นตอนของ start stage)
 Destroy stage (คือการทำงานของเมธออด destroy) ขั้นตอนนี้จะเกิดขึ้นเพียงครั้งเดียวเท่านั้น คือ ตอนที่ไม่ต้องการใช้แอพเพลตแล้วจริงๆ เช่น การปิดหน้าต่างเว็บบราวเซอร์ที่มีแอพเพลตถูกโหลดอยู่ลงไป เป็นต้น โดยแอพเพลตจะถูกลบออกจากความจำในขั้นตอนนี้
ตัวอย่างที่ 1 แสดงวงจรการทำงานของแอพเพลต
ไฟล์ MyApplet.java

หลังจากคอมไพล์โปรแกรม MyApplet.java เป็นไฟล์ class แล้ว ให้สร้างไฟล์เว็บเพจชื่อ MyApplet.java
ไฟล์ MyApplet.html

จากนั้นให้ใช้ appletviwer เรียกรันไฟล์ MyApplet.html โดยพิมพ์คำสั่งต่อไปนี้ที่ command prompt

ผลลัพธ์ของโปรแกรม

ผลลัพธ์ของโปรแกรมจะมีหน้าต่างแอพเพลตว่างๆแสดงขึ้นมา ดังรูป แต่ให้สังเกตที่หน้าต่าง command prompt จะพบว่ามีข้อความ init,start, และ paint แสดงขึ้นมาตามลำดับ
  
ตรงนี้แสดงให้เห็นว่าแอพเพลต เริ่มต้นทำงานด้วยเมธอด init และ startตามลำดับ จากนั้นจึงทำงานด้วยเมธอด paint
ให้ทดลองขยายหน้าต่างของแอพเพลต โดยคลิก บริเวณมุมบนขวา จะพบว่าที่ command p rompt มีข้อความ paint แสดงขึ้นมา ตรงนี้แสดงให้เห็นว่าทุกครั้งที่ทำการเปลี่ยนแปลงอะไรกับหน้าต่างของแอพเพลตก็ตาม เมธอด paint จะถูกเรียกให้ทำงาน
  
ต่อมาให้ทดลองคลิก เพื่อย่อหน้าของแอพเพลตหลงเป็นปุ่มบนทาสก์บาร์ (taskbar) สังเกตว่าที่ command promp t จะแสดงข้อความ stop เนื่องจากขณะนี้หน้าต่างของแอพเพลตไม่ได้แอคทีฟ จึงหยุดการทำงานของแอพเพลตชั่วคราวนั้นเอง แต่แอพเพลตยังคงอยู่ในหน่วยความจำ ยังไม่ถูกลบออกไป
  
จากนั้นนำเมาส์ไปคลิกที่แอพเพลตที่ถูกย่ออยู่บนทาสก์บาร์ เพื่อแสดงหน้าต่างของแอพเพลตกลับมาเหมือนเดิม จะพบว่ามีข้อความ start และ paint แสดงขึ้นมาที่หน้าต่าง command prompt ตามลำดับ เนื่องจากการแสดงหน้าต่างของแอพเพลต จะทำให้แอพเพลตกลับมาอยู่ในสถานะแอคทีฟอีกครั้ง ดังนั้นเมธอด start จึงถูกเรียกให้ทำงาน แล้วจึงทำงานต่อด้วยเมธอด paint
  
สุดท้ายให้ทดลองคลิก เพื่อปิดหน้าต่างของแอพเพลต สังเกตว่าที่ command prompt จะแสดงข้อความ stop เนื่องจากขณะนี้หน้าต่างของแอพเพลตไม่ได้แอคทีฟ จากนั้นจะแสดงข้อความ destroy ซึ่งแสดงให้เห็นว่าแอพเพลตถูกลบออกจากหน่วยความจำแล้วจริงๆ
  
ตัวอย่างที่ 2 แสดงการวาดเส้นลงบนแอพเพลต
ไฟล์ DrawLine.java

ไฟล์ DrawLine.html

ผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
การสร้างแอพเพลตไม่ใช่เรื่องยาก
เพียงแต่ผู้เขียนโปรแกรมต้องทราบว่าจะเลือกหยิบเมธอดไดร์จากแพคเกจได้มาใช้งานเท่านั้น ดังนั้นการอธิบายโปรแกรมในบทนี้จะอธิบายถึงการใช้งานเมธอดต่างๆ เพื่อที่ผู้อ่านจะได้ทราบว่าแต่ละเมธอดมีการใช้งานอย่างไร จะได้สามารถเลือกเมธอดมาใช้งานอย่างถูกต้องเหมาะสม และเกิดความชำนาญในการใช้งานเมธอดเหล่านั้นต่อไป
Void setBackground (Color c) ใช้กำหนดสีพื้นหลังให้กับแอพเพลต
Abstract void setColor(Color c) ใช้กำเนิดสี เพื่อนำสีนี้ไปใช้ในการวาดภาพกราฟิกว่าตัวอักษรต้องการ
Abstract void drawLine ( int x1, int y1, int x2, int y2 ) ใช้วาดเส้นตามสีปัจจุบันที่กำหนด โดยจะเริ่มวาดเส้นจากตำแหน่ง (x1 , y1) ไปถึงตำแหน่ง (x2 , y2)
บรรทัดที่ 13-17 จะวนลูปทั้งหมด 7 รอบเพื่อวาดเส้นลงบนแอพเพลต ดังนี้
รอบที่ 1 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 0,0 )
รอบที่ 2 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 50,0 )
รอบที่ 3 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 100,0 )
รอบที่ 4 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 150,0 )
รอบที่ 5 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 200,0 )
รอบที่ 6 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 250,0 )
รอบที่ 7 จะวาดเส้นจากตำแหน่ง ( width/2, height )ไปจนถึงตำแหน่งที่ ( 300,0 )
NOTE : ตำแหน่งหรือพิกัด ( 0,0 ) จะอยู่ที่มุมบนซ้ายของแอพเพลต สำหรับตำแหน่งอื่นๆจะวัดเทียบกับตำแหน่ง ( 0,0 )

ตัวอย่างที่ 3 แสดงการวาดวงรีและข้อความลงบนแอพเพลต
ไฟล์ OvalApplet.java

ไฟล์ OvalApplet.html

ผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
Abstract void fillOval ( int x , int y , int width , int height ) ใช้วาดวงรีตามสีปัจจุบันที่กำหนด โดยจะวาดวงรีให้อยู่ภายในกรอบสี่เหลี่ยมที่กำหนดขึ้นด้วยค่าของ x , y width และ height ดังรูป

ซึ่งจากตัวอย่างด้านบน เรากำหนด g.fillOvall (10,10,330,100) ; ดังนั้นวงรีจะถูกวาดให้อยู่ภายในกรอบสี่เหลี่ยมดังนี้

Abstract void fillOval ( int x , int y , int width , int height )ใช้วาดเส้นขอบของวงรีตามสีปัจจุบันที่กำหนด โดยจะวาดเส้นขอบของวงรีการเกี่ยวกับการวาดวงรี Abstract void setFont (Font font) ใช้กำหนดรูปแบบตัวอักษรที่ต้องการ โดยสามารถกำหนดได้ว่าจะใช้ฟอนต์ใด แสดงผลแบบใด (หนา, เอียง, ขีดเส้นใต้, ฯลฯ) และขนาดของตัวอักษรเป็นเท่าไร่ Abstract void drawString (String str , int x , int y ) ใช้วาดข้อความลงที่ตำแหน่ง ( x , y ) ของแอพเพลต
ตัวอย่างที่ 4 แสดงการวาดรูปทรงต่างๆลงบนแอพเพลต
- ไฟล์ DrawManyShape.java

- ไฟล์ DrawManyShape.html

ผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
- abstract void fillRect(int x, int y, int width, int height) ใช้วาดสี่เหลี่ยม โดยมุมหนึ่งของสี่เหลี่ยมจะอยู่ที่ตำแหน่ง (x,y) และความกว้างของสี่เหลี่ยมเท่ากับ width ส่วนความสูงของสี่เหลี่ยมเท่ากับ height ดังรูป

- void drawRect(int x, int width, int height) ใช้วาดเส้นขอบของสี่เหลี่ยมจากพิกัด (x,y) ไปจนถึง (x + width, y + height) เช่นเดียวกับการวาดสี่เหลี่ยม
- adstract void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) ใช้วาดโค้ง (โค้งนี้จะเป็นส่วนหนึ่งของวงกลมหรือวงรีก็ได้) ซึ่งจะวาดโค้งให้อยู่ภายในขอบเขตของกรอบสี่เหลี่ยมที่กำหนด โดยขอบเขตของกรอบสี่เหลี่ยมจะมีพิกัดเป็น (x,y) และ (x + width, y + height) โดยเริ่มต้นจุดโค้งที่มุม startAngle และ วาดโค้งไปทางด้านซ้ายในทิศทวนเข็มนาฬิกา ส่วนจะวาดโค้งไปกี่องศาเราจะใช้ arcAngle เป็นตัวกำหนด ดังนั้น จากตัวอย่างด้านบนที่ระบุวาดโค้งด้วย g.fillArc(120, 80, 170, 170, 0, 90) ; จึงหมายถึง ให้วาดโค้งโดยเริ่มต้นจุดโค้งที่มุม 0 และวาดโค้งไปทางด้านซ้าย 90 องศา
- adstract void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) การทำงานของเมธอดนี้จะเหมือนกับเมธอด fillArc เพียงแต่เมธอดนี้ใช้วาดขอบของเมธอดนี้ใช้วาดขอบของเส้นโค้ง ไม่ใช่พื้นที่ภายในโค้ง ดังนั้น จากตัวอย่างด้านบนที่ระบุวาดขอบของเส้นโค้งด้วย g.drawArcZ120, 20, 170, 170, 90, 180); จึงหมายถึง ให้เริ่มต้นวาดขอบของเส้นโค้งที่มุม 90 และวาดโค้งไปทางด้านซ้าย 180 องศา
- ไฟล์ JavaVersionApplet.java

- ไฟล์ JavaVersionApplet.html

ผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
- static String getProperty(String key) เป็นเมธอดของคลาส System ที่ใช้ตรวจสอบข้อมูลต่างๆ ของระบบปฏิบัติการ (operating system) ที่ใช้งานอยู่ซึ่งจากตัวอย่างด้านบนระบุคีย์เป็น java.version เพื่อค้นหาเวอร์ชันของตัวแปลภาษาจาวาที่ใช้งานอยู่ และคีย์ java.vendor เพื่อค้นหาว่าเจ้าของผลิตภัณฑ์ (ผู้พัฒนาตัวแปลภาษาจาวา) คือใคร โดยคีย์ที่สามารถระบุให้กับเมธอด getProperty ได้มีอยู่เป็นจำนวนมาก ดังนี้

ตัวอย่างที่ 5 แสดงการวาดข้อความลงบนแอพเพลตและเล่นเพลงจาก audio clip (ไฟล์ MIDI) เพื่อการร้องคาราโอเกะ
- ไฟล์ AudioClipSound.java


- ไฟล์ AudioClipSound.html

ผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
โปรแกรมนี้เป็นจาวาแอพเพลตที่แสดงเนื้อร้องพร้อมดนตรีของเพลง Have I you lately เพื่อให้ผู้ใช้ร้องคาราโอเกะ (ดนตรีมาจากไฟล์เพลงแบบ MIDI ที่ชื่อ Have I told you lately.mid) โดยในตัวอย่างนี้จะเก็บไฟล์เพลง Have I told you lately.mid ไว้ที่พาธ (path) เดียวกันกับไฟล์ AudioClipSound.html
- URL getDocumentBass() เป็นเมธอดในคลาส Applet ซึ่งเมธอดนี้จะคืนค่าเป็นออบเจ็คชนิด URL ที่เก็บค่าแอดเดรส (URL) ของเว็บเพจที่เรียกจาวาแอพเพลตตัวนี้ให้ทำงาน กล่าวคือ ตากตัวอย่างที่ 13.6 เมธอดนี้จะคืนค่า file:/C:/sourcejava/AudioClipSound.html ออกมาซึ่งค่านี้เป็นค่าแอดเดรสของไฟล์ AudioClipSound.html นั่นเอง
- AudioClip getAudioClip(URL url, String name) ใช้สร้างออบเจ็คชนิด AudioClip จากไฟล์เพลง (audio clip) ที่กำหนดโดยต้องระบุพารามิเตอร์ดังนี้
- พารามิเตอร์ตัวแรกของเมธอด ต้องระบุให้เป็นออบเจ๊คชนิด URL ที่เก็บค่าแอดเดรสของไฟล์ที่มีไฟล์เพลง Have I told you lately.mid ถูกโหลดอยู่ซึ่งก็คือ ต้องระบุเป็นค่าแอดเดรสของไฟล์ AudioClipSound.html นั่นเอง ดังนั้นในตัวอย่างที่ 13.6 บรรทัดที่ 5 จึงใช้ค่าจากเมธอด getDocumentBass เพื่อระบุเป็น URL ให้กับเมธอด getAudio
- พารามิเตอร์ตัวที่สองของเมธอด ต้องระบุให้เป็นพาธของไฟล์เพลง แต่กรณีนี้ไฟล์เพลงถูกเก็บอยู่ที่ค่าแอดเดรสเดียวกันกับไฟล์ AudioClipSound.html ดังนั้นในที่นี้จึงระบุเฉพาะชื่อไฟล์เพลงเท่านั้น ไม่ต้องระบุพาธอื่นเพิ่มเติมอีก แต่หากไฟล์เพลงอยู่คนละพาธกับไฟล์ AudioClipSound.html แล้ว ก็จะต้องระบุพาธของไฟล์เพลงด้วย
ยกตัวอย่างเช่น สมมติไฟล์ AudioClipSound.html และไฟล์เพลง Have I told you lately.mid ถูกเก็บอยู่ที่แอดเดรส http://musiclover.com เหมือนกัน การใช้งานเมธอด getAudio สามารถระบุได้ดังนี้
| AudioClip song = getAudioClip(getDocumentBase(), "Have I told you letely.mid"); |
แต่หากไฟล์ AudioClipSound.html ถูกเก็บอยู่ที่แอดเดรส http://musiclover.com แต่ไฟล์เพลง Have I told you lately.mid ถูกเก็บอยู่ที่แอดเดรส http://musiclover.com/audio แล้ว การใช้งานเมธอด getAudio สามารถระบุได้ดังนี้
| AudioClip song = getAudioClip(getDocumentBase(), "audio/Have I told you letely.mid"); |

การสืบทอดคุณสมบัติหรือ Inheritance เป็นคุณสมบัติหนึ่งของ OOPที่อนุญาตให้ผู้เขียนโปรแกรม สร้างคลาสใหม่โดยสืบทอดเอาคุณสมบัติต่างๆ มาจากคลาสเดิมที่มีอยู่แล้วได้ ซึ่งนับว่าเป็นข้อดีอย่างหนึ่งของการเขียนโปรแกรม ด้วยภาษาจาวา เนื่องจากการสืบทอดคุณสมบัติจะช่วยประหยัดเวลาในการเขียนโปรแกรม

เมื่อคลาสหนึ่งสืบทอดคุณสมบัติมาจากอีกคลาสหนึ่ง เราจะเรียกคลาสที่ถูกสืบทอดคุณสมบัติไปว่าคลาสแม่ (superclass) และเรียกคลาสที่สืบทอดคุณสมบัติมาว่า คลาสลุก (subclass) เช่น ถ้าพูดว่าคลาส A เป็นคลาสแม่ของคลาสคลาส B (หรือคลาส B เป็นคลาสลูกของคลาส A) จะหมายความว่าคลาส B ทำการสืบทอดคุณสมบัติมาจากคลาส A นั่นเอง

คีย์เวิร์ด extends ในภาษาจาวาใช้ระบุให้กับคลาสเพื่อกำหนดว่าคลาสนั้นต้องการสืบทอดคุณสมบัติมาจากคลาสใด
รูปแบบการระบุ extends ให้กับคลาส คือ
| modifier class ชื่อคลาส extends ชื่อคลาสที่ถูกสืบทอดคุณสมบัติ { } |
เช่น
- public class Student extends People { } เป็นการกำหนดให้คลาส Student สืบทอดคุณสมบัติมาจากคลาส People นั่นคือ คลาส Student จะเป็นคลาสลูกของคลาส People และคลาส People จะเป็นคลาสแม่ของคลาส Student
- public class Manager extends Employee { } เป็นการกำหนดให้คลาส Manager สืบทอดคุณสมบัติมาจากคลาส Employee นั่นคือ คลาส Manager จะเป็นคลาสลูกของคลาส Employee และคลาส Employee จะเป็นคลาสแม่ของคลาส Manager
คลาสแม่สามารถถ่ายทอดอะไรให้แก่คลาสลูกได้บ้าง?
สิ่งที่คลาสแม่จะถ่ายทอดให้แก่คลาสลูก คือ แอดทริบิวต์และเมธอด กล่าวคือ หากคลาสลูกทำการสืบทอดคุณสมบัติไปจากคลาสแม่แล้ว คลาสลูกจะสามารถเรียกใช้งานแอตทริบิวต์ และเมธอดที่มีอยู่ในคลาสแม่ได้ เสมือนกับว่าแอตทริบิวต์และเมธอดนั้นถูกสร้างไว้ในคลาสลูกเอง
และนอกจากนี้ เรายังสามารถกำหนดแอตทริบิวต์และเมธอดเพิ่มเติมเข้าไปในคลาสลูกได้ด้วย จึงทำให้คลาสลูกมีแอตทริบิวต์และเมธอดที่ได้รับการถ่ายทอดมาจากคลาสแม่ บวกกับแอตทริบิวต์และเมธอดที่ถูกกำหนดไว้ในคลาสลูกนั้นโดยเฉพาะ
ตัวอย่างที่ 1 แสดงการสืบทอดคุณสมบัติ โดยมีคลาส People.java เป็นคลาสแม่และคลาส ThaiStudent.java เป็นคลาสลูก
- ไฟล์ People.java

- ไฟล์ ThaiStudent.java

วิธีคอมไพล์โปรแกรม รันโปรแกรม และผลลัพธ์ของโปรแกรม

ในการสั่งคอมไฟล์โปรแรกม เราจะสั่งคอมไพล์จากคลาสที่เป็นคลาสลูกไม่ใช่สั่งคอมไพล์จากคลาสแม่ โดยเมื่อสั่งคอมไพล์คลาสลูกแล้วจะทำให้คลาสแม่ถูกคอมไพล์ไปโดยอัตโนมัติด้วย กล่าวคือ เมื่อสั่งคอมไพล์โปรแรกมด้วยคำสั่ง java ThaiStudent.java แล้ว จะทำให้คลาส ThaiStudent ถูกคอมไพล์ส่วนคลาส People ในไฟล์ People.java ก็จะถูกคอมไพล์โดยอัตโนมัติด้วย เนื่องจากคลาส ThaiStudent เรียกสืบทอดคุณสมบัติมาจากคลาส People
ทำไมต้องสืบทอดคุณสมบัติ
การที่ผู้เขียนนำหลักการของการสืบทอดคุณสมบัติมาใช้ก็เพื่อประหยัดเวลาในการสร้างคลาส คือ จะได้นำสิ่งที่มีอยู่แล้วในคลาสเดิมมาใช้ได้เลย โดยไม่ต้องเสียเวลาสร้างใหม่
ยกตัวอย่าง เช่น จากตัวอย่างที่ 1 สมมติว่าผู้เขียนไม่นำหลักการของการสืบทอดคุณสมบัติมาใช้มาดูกันว่าคลาส ThaiStudent ที่สร้างขึ้นเป็นอย่างไร


วิธีคอมไพล์โปรแกรม รันโปรแกรม และผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
จะเห็นว่าหากไม่ทำการสืบทอดคุณสมบัติโปรแกรมก็ยังคงได้ผลลัพธ์เหมือนเดิม เพียงแต่เราต้องเขียนโค้ดมากขึ้น โดยให้สังเกตโค้ดที่เป็นตัวหนา นั่นคือส่วนที่เราต้องเขียนเพิ่มขึ้นจากคลาส ThaiStudent ในตัวอย่างที่ 14.1 ซึ่งถ้าเรานำหลักการสืบทอดคุณสมบัติมาใช้ ก็จะไม่ต้องเขียนโค้ดส่วนที่เป็นตัวหนาเพราะโค้ดส่วนนี้จะได้รับการถ่ายทอดมาจากคลาสแม่ (คลาส People)
แต่ทั้งนี้ต้องขึ้นกับความเหมาะสม สมมติว่าผู้เขียนไม่เคยสร้างคลาส People ขึ้นมาก่อนและจากการออกแบบโปรแกรมพบว่าไม่มีคลาสใดเลยนอกเหนือจากคลาส ThaiStudent ที่จะประกอบด้วยแอตทริบิวต์และเมธอดในลักษณะนี้ ผู้ใช้ก็ไม่จำเป็นต้องนำหลักการสืบทอดคุณสมบัติแบบในตัวอย่างที่ 1 มาใช้ แค่ควรเลือกที่จะเขียนโค้ดเหมือนในตัวอย่างที่ 2 นี้จะสะดวกกว่า

หากเปรียบเทียบตัวอย่างที่ 1 และ 2 คงจะเห็นแล้วว่าตัวอย่างที่ 1 นำหลักการของการสืบทอดคุณสมบัติมาใช้ ทำให้สามารถนำคลาส People ที่มีอยู่แล้วกลับมาใช้ใหม่ (re-use) ได้โดยที่ไม่ต้องเขียนโค้ดซ้ำๆ ให้ยุ่งยากดังเช่นตัวอย่างที่ 2

ถ้าเมธอดที่กำหนดในคลาสลูกมีชื่อของเมธอด, ค่าที่ส่งคืนกลับออกไปจากเมธอด และอร์กิวเมนต์ทุกอย่างตรงกับเมธอดในคลาสแม่แล้ว เราจะเรียกเมธอดในคลาสลูกนี้ว่าเป็นเมธอดที่ทำการ override เมธอดเดิมที่มีอยู่ในคลาสแม่
เมธอดในคลาสลูกที่ทำการ override เมธอดเดิมที่มีอยู่ในคลาสแม่ จะช่วยให้คลาสลูกสามารถแก้ไขหรือเพิ่มเติมการทำงานบางอย่างของเมธอดที่ได้รับการถ่ายทอดมาจากคลาสแม่ได้ ซึ่งกระบวนการนี้เรียกว่า method overriding
ตัวอย่างที่ 3 แสดงการทำ method overriding (สร้างเมธอดในคลาสลูกซึ่งทำการ override เมธอดที่ได้รับมาจากคลาสแม่)
- ไฟล์ CompanyEmployee.java

- ไฟล์ ThaiManager.java

วิธีคอมไพล์โปรแกรม และผลลัพธ์ของโปรแกรม

อธิบายโปรแกรม
คลาส ThaiManager ทำการ override เมธอด getInformation ที่ได้รับการถ่ายทอดมาจากคลาสแม่ (คลาส CompanyEmployee) เพื่อเปลี่ยนแปลงการทำงานของเมธอดนี้ โดยจากเดิมที่เมธอดนี้มีการกำหนดแอตทริบิวต์ department ขึ้นมาด้วย ดังนั้นเมธอด getInformation ในคลาส ThaiManager จึงคืนค่า department กลับออกไปด้วยอีกค่าหนึ่ง
คอนสตรัคเตอร์ในคลาสแม่จะไม่ถูกถ่ายทอดให้คลาสลูก
คลาสแม่จะถ่ายทอดเพียงแค่แอตทริบิวต์และเธอดให้หกับคลาสลูกเท่านั้น แต่คอนสตรัคเตอร์ในคลาสแม่จะไม่ถูกถ่ายทอดไปยังคลาสลูก (ในการถ่ายทอดคุณสมบัติจะมีเพียงแค่แอคทริบิวต์และเมธอดที่ประกาศด้วย modifier public และ protected จะไม่ถูกถ่ายทอดให้กับคลาสลูก สำหรับแอตทริบิวต์และเมธอดที่ถูกประกาศด้วย modifier private จะไม่ถูกถ่ายทอดให้คลาสลูก แต่กรณีที่คลาสลูกอย่ในแพ็กเกจเดียวกันกับคลาสแม่ แอตทริบิวต์และเมธอดที่ถูกประกาศด้วย modifier package ก็จะถูกถ่ายทอดให้กับคลาสลูกด้วย)
สรุป คือ คอนสตรัตเตอร์ของคลาสแม่และคลาสลุก เป็นส่วนที่แยกออกจากกัน ไม่สามารถสืบทอดให้กันได้
ตัวอย่างที่ 4 แสดงการทำงานของคลาสแม่ที่จะไม่ถ่ายทอดคอนสตรัคเตอร์ไปยังคลาสลูก
- ไฟล์ TestInheritance.java

วิธีคอมไพล์โปรแกรม
โปรแกรมนี้คอมไฟล์ไม่ผ่าน โดยเกิดข้อผิดพลาดขึ้นดังนี้

แม้ว่าคลาส B จะสืบทอดคุณสมบัติมาจากคลาส A ก็ตาม แต่คอนสตรัคเตอร์ A(int num) ในบรรทัดที่ 4-7 จะไม่ถูกถ่ายทอดไปยังคลาส B กล่าวคือ จะไม่มีคอนสตรัคเตอร์ B(int num) ถูกสร้างขึ้นโดยอัตโนมัติเพื่อให้เรียกใช้งาน
นี่คือเหตุผลที่ทำให้เกิดข้อผิดพลาดขึ้นในการคอมไพล์โปรแกรม เพราะบรรทัดที่ 24 ของโปรแกรมเป็นการเรียกคอนสตรัคเตอร์ B(int num) ให้ทำงาน แต่ไม่มีคอมสตรัคเตอร์ลักษณะนี้กำหนดอยู่ในคลาส B เลย
ผู้เขียนทดสอบนำคอมเมนต์ในบรรทัดที่ 16 ออก แล้วคอมไพล์โปรแกรมใหม่อีกครั้ง ซึ่งครั้งนี้จะพบว่าคอมไพล์ผ่าน และเมื่อรันโปรแกรมจะได้ผลลัพธ์ ดังนี้
|