Lab 4 – Interface, Abstract class.
วัตถุประสงค์:
- ให้ทดลองอินเตอร์เฟสและ Abstract class
ให้สร้างอินเตอร์เฟส CompareSizeAble (ของที่จะเป็น CompareSizeAble นั้น จะต้องเปรียบเทียบขนาดกันได้) ซึ่งมีเมธอด public int isLargerThan(
CompareSizeAble other);
โดย
- this และ other จะต้องเป็นออบเจ็กต์ของคลาสเดียวกัน
- เมธอดนี้รีเทิร์น
- 1 ถ้า this นั้นใหญ่กว่า other
- 0 ถ้า this นั้นขนาดเท่ากับ other
- -1 ถ้า this นั้นขนาดเล็กกว่า other
ต่อจากนี้ เราจะมานิยามคลาสที่ออบเจ็กต์ของมันเปรียบเทียบขนาดกันได้
- ให้มีคลาส Mecha
ซึ่งเป็นคลาสพื้นฐานในการจำลองหุ่นยนต์และเครื่องจักรในเกมเกมหนึ่ง
(แต่ไม่สามารถนำคลาสนี้มาสร้างออบเจ็กต์ได้โดยตรง เพราะว่า เมธอด lockon
เป็นเมธอดที่ผู้ออกแบบโค้ดถือว่านิยามไม่ได้)
- ตัว Mecha นั้นมี
- ตัวแปร height, width, x, y ซึ่ง x, y เป็นค่าตำแหน่งในโลกสามมิติ ทุกตัวให้เป็นจำนวนเต็ม
- มีชื่อของ Mecha เป็น String
- เมธอด get กับ set ของทุกตัวแปร
- เมธอด public void
lockon(Mecha[][] x) ซึ่งเป็นการเล็งเป้ายิงศัตรูในเกม
เมธอดนี้จะต่างกันไปสำหรับ Mecha แต่ละชนิด โดยรับแผนที่ x เข้ามา
แล้วเมธอดจัดการสิ่งต่างๆภายในออบเจ็กต์ สำหรับคลาส Mecha เองนั้น
เราถือว่าเมธอดนี้นิยามไม่ได้
- ให้มีคลาส MobileArmor ซึ่งเป็นการจำลองยานรบขนาดใหญ่
- ให้ถือว่า MobileArmor เป็น Mecha ชนิดหนึ่ง
- เมื่อสร้างขึ้นมา มีค่า default ต่างๆ(สำหรับตัวแปร primitive) เป็น 3 ส่วนชื่อให้เป็น "unknown"
- มีตัวแปร currentlyLock เป็นอาร์เรย์ของ Mecha
ซึ่งอาร์เรย์นี้แทนยานหรือหุ่นศัตรูทั้งหมดที่ถูกล็อคเป้าได้ (MobileArmor สามารถล็อคได้ทีเดียวหลายเป้า)
- จำนวนหุ่นที่ล็อคได้ ขึ้นอยู่กับขนาดของ MobileArmor
โดยถ้ามีขนาด width ไม่เกิน 5 ให้ล็อคเป้าได้ 2 ตัว ถ้าเกินกว่านั้น
ให้ล็อคได้ 4 ตัว
- ตอนเริ่มต้น อาร์เรย์นี้จะว่าง
- เขียนเมธอด lockon
ซึ่งเป็นการเก็บ Mecha ต่างๆที่อยู่บนแผนที่
(ขอให้ดูนิยามแผนที่) เก็บเข้าอาร์เรย์ currentlyLock โดย
เก็บจาก Mecha ที่อยู่ใกล้ตัว MobileArmor นั้นที่สุดก่อน(นับรัศมี)
จนเต็มเท่าที่ currentlyLock จะเก็บได้ รัศมีการล็อค ขึ้นอยู่กับ width
ของ MobileArmor ตัวที่จะล็อคเค้า โดยนับจำนวนช่องออกไป (ตาม width โดยรอบ)
เป็นกรอบสี่เหลี่ยมแต่ละระดับ
แต่ถ้ามีหลายตัวอยู่ใกล้กับ MobileArmor เท่ากัน
ให้ล็อคด้านบนซ้ายในกรอบที่อยู่ห่างจากตัว MobileArmor
เท่ากันก่อนแล้วเรียงการล็อคตามเข็มนาฬิกา
- ให้คลาสนี้เป็น CompareSizeAble ด้วย โดย MobileArmor ที่ใหญ่กว่านั้น ดูจากความกว้าง
- ให้นิสิตเขียนเมธอดเพิ่มเองได้ตามใจ
- ให้มีคลาส MobileSuit ซึ่งเป็นการจำลองหุ่นยนต์รบ
- ให้ถือว่า MobileSuit เป็น Mecha ชนิดหนึ่ง
- เมื่อสร้างขึ้นมา มีค่า default ต่างๆ (สำหรับตัวแปร primitive) เป็น 1 ส่วนชื่อนั้นมีค่า default เป็น "unknown"
- มีตัวแปร currentlyLock เป็น Mecha ซึ่งตัวแปรนี้แทน Mecha
ที่จะถูกหุ่นยนต์รบตัวนี้ล็อคเป้าได้ ตอนเริ่มโปรแกรม ตัวแปรนี้จะเป็น null
- เขียนเมธอด lockon ซึ่งเป็นการเก็บ Mecha
ที่ใกล้ตัวหุ่นยนต์นี้ที่สุด (นับรัศมี) ในแผนที่ไว้ตรง currentlyLock
ซึ่ง รัศมีที่ MobileSuit จะยิงศัตรูได้จะอยู่ที่ 2 หน่วยเท่านั้น
- ถ้าเกิดมีหลายตัวอยู่ใกล้สุดเท่ากัน ให้ยิง MobileSuit ก่อน MobileArmor
(scan การล็อคเป้า ตามเข็มนาฬิกาจากจุดบนซ้าย เริ่มจากรัศมี 1 ก่อน แล้วทำออกไปเรื่อยๆ แบบเดียวกับของ MobileArmor)
- ให้คลาสนี้เป็น CompareSizeAble ด้วย โดย MobileSuit ที่ใหญ่กว่านั้น ดูจากความสูง
- ให้นิสิตเขียนเมธอดเพิ่มเองได้ตามใจ
- สำหรับแผนที่นั้นเป็นอาร์เรย์สองมิติของ Mecha ซึ่งมีขนาด 5x5
- จงเขียนคลาส MapTest
- ในคลาส MapTest จงเขียนเมธอด
public
static Object findLargest(Object object1, Object object2) ซึ่งรีเทิร์น object ที่ใหญ่กว่า ในการเปรียบเทียบ object สองตัว ออกมา โดยใช้การเปรียบเทียบ
CompareSizeAble สองตัว
- เราจะมารันโค้ดทดสอบเมธอดต่างๆในคลาส MapTest นี้กัน เพื่อการทดสอบที่แน่นอน จงให้แผนที่เริ่มต้นเป็นดังนี้
A2(w=3) |
|
M2(h=3) |
M4(h=3) |
A4(w = 3) |
M3(h=1) |
|
|
|
|
|
|
|
A3(w=2) |
|
|
M1(h=2) |
|
|
M5(h=2) |
A1(w=6) |
|
|
|
|
โดย A แทน MobileArmor ต่างๆ และ M แทน MobileSuit ต่างๆ (h
คือความสูง ส่วน w คือ ความกว้าง อันไหนที่ไม่ได้ระบุ ให้มีค่า default) ค่าตำแหน่งของแผนที่ ให้ (0,0) เป็นตำแหน่งช่องซ้ายล่าง
เขียนโค้ดทดสอบ เพื่อทำการทดสอบดังนี้
- ให้ M4 กับ M5 ล็อคเป้า แล้วพิมพ์สิ่งที่ล็อคออกมา
- ให้ A1 กับ A3 ล็อคเป้า แล้วพิมพ์สิ่งที่ล็อคออกมา
- เรียกใช้
findLargestโดยเปรียบเทียบ A1 กับ A2, A3 กับ A4, M1 กับ M2, และ M2 กับ M5 แสดงผลให้เรียบร้อย
ส่วนต่อไปนี้ทดลองเฉยๆ ไม่ต้องส่ง
จากนั้นลองเปลี่ยน interface CompareSizeAble ให้มีเมธอด public boolean isItBig();
จะพบว่า โปรแกรมที่เขียนมาแล้วจะใช้ไม่ได้เลย
เพราะอินเตอร์เฟสจะไปบังคับให้คลาสต่างๆเขียนโค้ดของ isItBig ทั้งหมด
ซึ่งผู้ที่ implement อินเตอร์เฟสนั้นจะต้องเข้าไปเขียนในทุกโค้ด
- ซึ่งก็เป็นข้อดี ตรงที่ทุกคลาสต้องได้รับการอัพเดทให้ใช้อินเตอร์เฟสได้ถูกต้อง
- แต่ก็เป็นข้อเสียตรงที่ จริงๆแล้ว เราอาจต้องการอัพเกรดแค่บางคลาสเท่านั้น
วิธีแก้ คือ เราเขียนอินเตอร์เฟสใหม่ ให้ extends มาจากอินเตอร์เฟสเดิม
(ใช่แล้ว ใช้ extends กับอินเตอร์เฟสได้) แล้วค่อยไปแก้ให้คลาส implement
อินเตอร์เฟสใหม่แทน สำหรับคลาสที่ต้องการการอัพเดทเท่านั้น ลองทำดู
แล้วจะเห็นว่าคอมไพล์ผ่าน
การส่ง
export ไฟล์เป็น jar file (ต้องมีซอร์สโค้ด ตรวจทานให้ดี) แล้วส่งมาที่ progmethcp@gmail.com ภายในวันพุธที่ 8 กรกฎาคม เวลา 24.00 น. ไฟล์จะต้องตั้งชื่อว่า lab04_xxxxxxxxxx.jar
โดย xxxxxxxxxx นั้นเป็นเลขประจำตัวนิสิต ส่วนใน subject ของเมล์ ให้ใส่
lab04_ xxxxxxxxxx โดย xxxxxxxxxx นั้นเป็นเลขประจำตัวนิสิต