MountainBike นั้น มีเมธอดที่ inherit มาจาก Bicycle 4 เมธอด ตัวแปรที่ inherit มากจาก Bicycle 3 ตัว มีเมธอดของมันเองอย่างเดียวที่เพิ่มมา คือ setHeight เท่านั้น และมีตัวแปรของมันเองอย่างเดียวที่เพิ่มมา คือ seatHeight รวมแล้ว มีเมธอดทั้งหมด 5 เมธอด ตัวแปรทั้งหมด 4 ตัวแปร ส่วน constructor นั้นไม่ inherit มา เมื่อตัวแปรทุกตัวถูกเปลี่ยนให้เป็น private พบว่า ในสับคลาส อ่านค่าโดยตรงของตัวแปรเหล่านั้นไม่ได้ ใน main ของคลาสอีกคลาส ก็อ่านไม่ได้เหมือนกัน เมื่อสร้างเมธอดขึ้นมาเพื่ออ่านและเขียนค่าตัวแปร (public เมธอด นะ) แล้วเรียกใช้เมธอดเหล่านี้ใน main ของสับคลาส พบว่า เมธอดสามารถอ่านและเขียนค่าได้ นั่นคือ ตัวแปรได้รับการ inherit มาจริง เมื่อเอา main ไปเขียนในคลาสใหม่ พบว่า รันได้เหมือนกัน เมื่อตัวแปรทุกตัวถูกเปลี่ยนให้เป็น protected พบว่า ในสับคลาส อ่านค่าโดยตรงของตัวแปรเหล่านั้นได้ ใน main ของคลาสอีกคลาส ก็สั่งอ่านได้โดยตรงเหมือนกัน เมื่อสร้างเมธอดขึ้นมาอ่านและเขียนค่าตัวแปร แล้วเรียกใช้ใน main ของสับคลาส พบว่า เมธอดสามารถอ่านและเขียนค่าได้ เมื่อเอา main ไปเขียนในคลาสใหม่ พบว่า รันได้เหมือนกัน เมื่อตัวแปรเป็น private เมธอดเป็น private พบว่า main ใน MountainBike ไม่คอมไพล์เพราะมองไม่เห็นเมธอดที่เราเรียก main ในอีกคลาสหนึ่งก็เช่นเดียวกัน เมื่อตัวแปรเป็น private เมธอดเป็น protected พบว่า main ทั้งใน MountainBike และ ในอีกคลาส รันได้ทั้งคู่ เมื่อตัวแปรเป็น protected เมธอดเป็น private พบว่า main ทั้งใน MountainBike และ ในอีกคลาส มองไม่เห็นเมธอดที่เป็น private เมื่อตัวแปรเป็น protected เมธอดเป็น protected พบว่า main ทั้งใน MountainBike และ ในอีกคลาส รันได้ทั้งคู่ Object a = new MountainBike(); คอมไพล์ไม่ผ่าน เนื่องจากเราไม่มี constructor ของ MountainBike ที่ไม่มี argument. ในตอนแก้จึงได้เติม constructor นั้นไป แต่ก็เจอปัญหาตามมาอีกหนึ่งอย่าง เพราะภายใน MountainBike() {} นั้น โค้ดพยายามเรียก Bicycle() {} จาก superclass ซึ่งไม่มีตัวตน โปรแกรมไม่ยอมคอมไพล์ ดังนั้นในที่สุดผมจึงต้องสร้าง constructor Bicycle(){ } ขึ้นมาด้วย โปรแกรมไม่คอมไพล์ โดยมันบอกว่าไม่สามารถเปลี่ยน Object เป็น MountainBike แต่ถ้าเราใช้การ cast ก็จะคอมไพล์ผ่าน เมื่อเปลี่ยน new MountainBike เป็น new Bicycle แล้ว เกิด exception -Bicycle cannot be cast to MountainBike สาเหตุน่าจะเป็นเพราะเราพยายามใช้ myBike ในฐานะ MountainBike แต่ว่า a จริงๆแล้วไม่ได้สร้างมาจากสิ่งที่ชัวร์ว่าจะเป็น MountainBike ดังนั้นจึงส่งผลให้ convert ไทป์ไม่ได้ ---------------------------------------------------------------------------------------- ถ้ารัน Cat โดยไม่ได้เปลี่ยนอะไรเลย เราที่พิมพ์ออกมาได้ว่า The class method in Animal. The instance method in Cat. เมื่อเพิ่มเข้าไปหนึ่งบรรทัด เพื่อทดสอบการรันคลาสเมธอด เราพบว่า Cat.testClassMethod(); ไปรันเมธอดในคลาส Cat แสดงว่า class method นั้น ตัวคลาสเป็นตัวบอกเราโดยตรงว่าจะรันเมธอดของคลาสนั้นๆ แม้ว่าเราจะใช้ตัวออบเจ็กต์ในการเรียกเมธอด เช่น myAnimal.testClassMethod() ผลก็จะเป็น เรียกใช้ตามคลาสของออบเจ็กต์นั้นอยู่ดี ลองเปลี่ยนต่อ ใช้ new Animal() จะไม่คอมไพล์ เพราะ Animal object เอามาใช้ในฐานะ Cat ไม่ได้ คราวนี้ลองเปลี่ยนโค้ดให้ด้านซ้ายมือทั้งหมดเป็น ไทป์ Animal Animal myCat = new Cat(); Animal myAnimal = myCat; myAnimal.testInstanceMethod(); ผลการรันคือ มันรันเมธอดใน Cat อยู่ดี ดังนั้นจึงได้ว่า ไม่ว่าตัวแปรจะมีไทป์อะไร เมธอดของตัวออบเจ็กต์จริงจะได้รันเสมอ ต่อไปก็ลอง Animal myCat = new Animal(); Cat myAnimal = myCat; แล้วไม่ยอมคอมไพล์ เพราะว่า myCat มีไทป์เป็น Animal เอามาทำเป็น Cat ซึ่งเล็กกว่าไม่ได้ เมื่อลองใช้ public static void main(String[] args) { Cat myCat = new Cat(); Animal myAnimal = myCat; Animal.testClassMethod(); myAnimal.a(); } ปรากฎว่า คอมไพเลอร์ไม่ยอมให้รันผ่าน ทั้งๆที่ ตัว object มีเมธอด a อยู่ คาดว่าเป็นเพราะไทป์ของ myAnimal เพราะว่าใน Animal ไม่มี a() ดังนั้นจึงเป็นข้อสังเกตว่า เมธอดจะเรียกใช้ได้ตามไทป์ของออบเจ็กต์เท่านั้น เมื่อเรียก b() จะปรากฎว่า คอมไพล์ผ่าน และไปเรียกเมธอดที่นิยามในคลาส Animal มาใช้งาน ซึ่งน่าจะมาจากการที่ Cat inherit method มาจาก Animal คือตอนที่จะเรียก b() นั้น ดูจากไทป์ แต่ตอนเรียกจริงเรียกจากตัวออบเจ็กต์ ซึ่งพอดี Cat ก็มีเมธอด b() แต่อยู่ในรูปที่ inherit มาจาก Animal ------------------------------------------------- จากการรันเมธอด printMethod() เราจะได้ว่า output คือ Printed in Superclass. Printed in Subclass ซึ่งบอกสาเหตุเราได้ว่า s.printMethod() ไปเรียก printMethod ของ Superclass ก่อน ด้วยคีย์เวิร์ด super จากนั้นจึงรันโค้ดส่วนที่เหลือใน printMethod ของ Subclass