720 likes | 1.04k Views
การสืบทอด ( inheritance). Nerissa Onkhum. Outline. การสืบทอด การเข้าใช้แบบ protected พอลิมอร์ฟิซึม การสืบทอดในภาษาจาวา คลาส Object. การสืบทอด. การสืบทอด ( Inheritance ). ในการโปรแกรมเชิงวัตถุเป็นแนวความคิดที่เลียนแบบจาก การลืบทอดลักษณะของลูกมาจากพ่อและแม่
E N D
การสืบทอด (inheritance) Nerissa Onkhum
Outline • การสืบทอด • การเข้าใช้แบบ protected • พอลิมอร์ฟิซึม • การสืบทอดในภาษาจาวา • คลาส Object
การสืบทอด (Inheritance) • ในการโปรแกรมเชิงวัตถุเป็นแนวความคิดที่เลียนแบบจากการลืบทอดลักษณะของลูกมาจากพ่อและแม่ • การโปรแกรมเชิงวัตถุนำการลืบทอดมาใช้กับคลาสและอินเทอร์เฟส • การสืบทอดเกี่ยวข้องกับคลาส 2 คลาส คือคลาสแม่และคลาสลูก • คลาสแม่จะถ่ายทอดความสามารถและลักษณะให้กับคลาสลูก • คลาสแม่จะนำเสนอแนวความคิดที่กว้างและทั่วไป • คลาสลูกจะนำเสนอแนวความคิดที่เฉพาะเจาะจง หรือมีความสามารถเพิ่มเติมจากที่มีอยู่แล้วในคลาสแม่
สัตว์ต่างๆ • คลาสแมว • แอตทริบิวต์ ได้แก่ อายุ และ ความหิว • เมธอด ได้แก่ กิน() และ นอน() • คลาสปลา • แอตทริบิวต์ ได้แก่ อายุ ความหิว และชื่อ (เช่น ปลานีโม) • เมธอด ได้แก่ กิน() และ นอน() • คลาสลิง • แอตทริบิวต์ ได้แก่ อายุ และ ความหิว • เมธอดได้แก่ กิน() นอน() และเก็บลูกมะพร้าว()
แอททริบิวท์และเมธอดที่คล้ายกันแอททริบิวท์และเมธอดที่คล้ายกัน
การสืบทอด • แก้ปัญหาการเขียนโปรแกรมซ้ำซ้อนกันได้ • เมธอดหรือแอตทริบิวต์ที่คลาสต่างๆ มีร่วมกันจะถูกนำไปใส่ในคลาสแม่ • คลาสลูกจะสืบทอดเมธอดและแอตทริบิวต์คลาสแม่โดยอัตโนมัติ • การแก้ไขเปลี่ยนแปลงเมธอดในคลาสแม่จะทำให้คลาสลูกเปลี่ยนตามไปด้วย
คลาสสัตว์ • แมว ปลา และลิง เป็นสัตว์ สัตว์ทุกตัวสามารถกินและนอนได้ เราจึงนำแอตทริบิวต์และเมธอดที่สัตว์ต่างๆมีร่วมกัน ไปใส่ในคลาสสัตว์ class สัตว์ { // แอตทริบิวต์ อายุ; ความหิว; // เมธอด กิน() {… } นอน() {… } }
การสืบทอด • รูปแบบ • classคลาสลูกextendsคลาสแม่ • ตัวอย่าง class แมว extends สัตว์ { } class ปลา extends สัตว์ { } class ลิง extends สัตว์ { }
การทดสอบการสืบทอด • แต่งประโยคโดยใช้คำว่า “เป็น” เข้าช่วย • ลิงเป็นสัตว์ • สัตว์เป็นลิง • ลิงไซบอร์ก เป็น ลิงและหุ่นยนต์ • รถยนต์เป็นพาหนะ class ลิง extends สัตว์ class รถยนต์ extends พาหนะ
การทดสอบการสืบทอด • แต่งประโยคโดยใช้คำว่า “เป็น” เข้าช่วย • เครื่องยนต์เป็นรถยนต์ • รถยนต์มีเครื่องยนต์ class รถยนต์ extends พาหนะ{ เครื่องยนต์ // แอตทริบิวต์ห }
วัตถุในคลาสลูกสามารถทำงานตามเมธอดของคลาสแม่ได้วัตถุในคลาสลูกสามารถทำงานตามเมธอดของคลาสแม่ได้ ลิง ล = new ลิง(); ล.กิน(); คลาสลิงไม่มีเมธอดใด ๆ ประกาศไว้ ล.กิน(); จึงไปทำงานตามเมธอด กิน() ที่อยู่ในคลาสแม่ (คลาสสัตว์)
วัตถุในคลาสลูกสามารถทำงานตามเมธอดของคลาสแม่ได้วัตถุในคลาสลูกสามารถทำงานตามเมธอดของคลาสแม่ได้ ลิง ล = new ลิง(); ล.กิน(); สรุป คือ ถ้าคลาสลูกไม่ได้เขียนเมธอด กิน() วัตถุในคลาสลูกจะเข้าไปเรียกใช้ เมธอดกินที่คลาสแม่ ดังนั้น การเปลี่ยนแปลงการทำงานของเมธอดในคลาสแม่ ทำให้การทำงานของลูกทุกคลาสเปลี่ยนแปลงตาม โดยอัตโนมัติ
เพิ่มเมธอดในคลาสลูก class ลิง extends สัตว์ { // เมธอดที่เพิ่มเข้ามา เก็บลูกมะพร้าว() { … } } ลิง ล = new ลิง(); ล.เก็บลูกมะพร้าว(); สัตว์ ส = new สัตว์(); ส.เก็บลูกมะพร้าว(); คอมไพล์ผ่าน เพราะเรฟเฟอร์เรนซ์ของลิง สามารถเรียกใช้เมธอดของลิงได้ คอมไพล์ไม่ผ่าน สัตว์โดยทั่วไปไม่รู้วิธีเก็บลูกมะพร้าว
เพิ่มเมธอดในคลาสลูก สรุป • วัตถุในคลาสลูกสามารถเรียกเมธอดจากคลาสแม่ได้ • แต่วัตถุในคลาสแม่ ไม่สามารถเรียกเมธอดที่ถูกเขียนเพิ่มเติมในคลาสลูกได้ • การเพิ่มความสามารถในคลาสลูก ทำให้การพัฒนาต่อยอดทำได้ง่ายขึ้น • ผู้เขียนโปรแกรมสามารถสร้างคลาสใหม่โดยการสืบทอดจากคลาสเดิม และเขียนเมธอดเพิ่มเติมลงในส่วนที่คลาสเดิมไม่มี
เพิ่มแอททริบิวท์ในคลาสลูกเพิ่มแอททริบิวท์ในคลาสลูก class ปลา extends สัตว์ { // แอตทริบิวต์ที่เพิ่มเข้ามา ชื่อ; } • สามารถประกาศแอตทริบิวต์เพิ่มเติมให้กับคลาสลูกได้
เพิ่มแอททริบิวท์ในคลาสลูกเพิ่มแอททริบิวท์ในคลาสลูก • ปกติจะไม่ให้คลาสอื่นเข้าถึงแอตทริบิวต์ได้โดยตรง • แอตทริบิวต์ จึงถูกประกาศการเข้าใช้เป็น private • การเข้าใช้แบบ private คลาสลูกก็ไม่สามารถเข้าใช้แอตทริบิวต์ได้ • ตัวอย่างเช่น ถ้าแอตทริบิวต์ “อายุ” ของคลาสสัตว์เป็น private • คลาสแมวซึ่งเป็นคลาสลูกของสัตว์ จะไม่สามารถเข้าใช้แอตทริบิวต์ “อายุ” ได้ • ถ้าอยากให้คลาสลูกใช้งานแอตทริบิวต์ของแม่ได้ ต้องเปลี่ยนระดับการใช้งานเป็น “protected”
เพิ่มแอททริบิวท์ในคลาสลูกเพิ่มแอททริบิวท์ในคลาสลูก • protected คือการกำหนดให้คลาสลูกละคลาสในแพ็จเกจเดียวกันสามารถเข้าใช้ได้ • protected • เข้มงวดน้อยกว่า private • อิสระน้อยกว่าแบบ public class สัตว์{ protected อายุ; } class ลิง{ ทำให้แก่(){ อายุ +=10; } }
เมธอดที่ชื่อซ้ำกับเมธอดในคลาสแม่เมธอดที่ชื่อซ้ำกับเมธอดในคลาสแม่ class ปลา extends สัตว์ { // แอตทริบิวต์ ชื่อ; // เมธอด นอน() { // วิธีการนอนของปลา … } }
การโอเวอร์ไรด์เมธอด • คลาสสัตว์มีเมธอด นอน(); • เขียนเมธอด นอน(); ซ้ำอีกในคลาสปลา • การเขียนเมธอดที่มีชื่อและพารามิเตอร์เหมือนกับ เมธอดเดิมที่มีอยู่ในคลาสแม่ เรียกว่า การโอเวอร์ไรด์ (override) • วัตถุในคลาสลูกได้รับคำสั่งให้เรียกใช้เมธอดที่ถูก โอเวอร์ไรด์วัตถุนั้นจะทำงานตามเมธอดที่เขียนในคลาสลูก • ปลา ป = new ปลา(); ป.นอน();
เรฟเฟอร์เรนซ์ของคลาสแม่สามารถอ้างถึงคลาสลูกได้เรฟเฟอร์เรนซ์ของคลาสแม่สามารถอ้างถึงคลาสลูกได้ • ต้องการใช้งานวัตถุคลาสใด จะประกาศเรฟเฟอร์เรนซ์ของคลาสนั้น เช่น ถ้าต้องการใช้งานปลา • ปลา ป = new ปลา(); • แต่ถ้าเป็นเรื่องการสืบทอด สามารถให้เรฟเฟอร์เรนซ์ของคลาสแม่อ้างถึงวัตถุในคลาสลูก • ตัวอย่างเช่น คลาสปลาสืบทอดคลาสสัตว์ ดังนั้น เรฟเฟอร์เรนซ์คลาสสัตว์อ้างถึงปลาได้ • สัตว์ ส = new ปลา();
เรฟเฟอร์เรนซ์ของคลาสแม่สามารถอ้างถึงคลาสลูกได้เรฟเฟอร์เรนซ์ของคลาสแม่สามารถอ้างถึงคลาสลูกได้ • สามารถสั่งให้วัตถุในคลาสลูก ทำงานได้โดยผ่านทาง เรฟเฟอร์เรนซ์ของคลาสแม่ได้ • สัตว์ ส = new ปลา(); ส.นอน(): • ถ้าใช้เรฟเฟอร์เรนซ์คลาสแม่อ้างถึงวัตถุคลาสลูก จะเรียกใช้ได้เฉพาะเมธอดที่มีในคลาสแม่เท่านั้น ไม่เช่นนั้นคอมไพล์จะไม่ผ่าน • สัตว์ ส = new ลิง()ว ส.กิน(); ส.เก็บลูกมะพร้าว();
พอลิมอร์ฟิซึม ส.นอน() สามารถตีความได้หลายแบบ ขึ้นอยู่กับวัตถุที่ ส อ้างถึง
ความหมายของโพลิมอร์ฟิซึมความหมายของโพลิมอร์ฟิซึม • poly แปลว่าหลายหรือมาก • morphism นั้นมาจากคำว่า morph ซึ่งแปลว่ารูปร่าง • รวมกันแล้วหมายถึงความสามารถที่สิ่งหนึ่งจะมีได้หลายรูปร่าง ซึ่งเมื่อใช้คำนี้กับการโปรแกรมเชิงวัตถุ ก็จะหมายถึงการที่คำสั่งแบบเดียวกันสามารถถูกแปลได้หลายแบบ
พอลิมอร์ฟิซึมกับการนำกลับมาใช้ใหม่ • พอลิมอร์ฟิซึมสนับสนุน การนำกลับมาใช้ใหม่(reuse) • ถ้าเราได้เขียนโปรแกรมที่ใช้งานได้กับสัตว์ โปรแกรมของเราย่อมใช้ได้กับแมว ปลา และลิงนอกจากนั้นถ้ามีคนสร้างคลาสอีกัวน่าขึ้นมาใหม่ โปรแกรมที่เราเขียนก็สามารถใช้ได้กับคลาสอีกัวน่าเช่นกัน
คลาสรูปร่างและคลาสที่สืบทอดคลาสรูปร่างและคลาสที่สืบทอด
คลาสรูปร่าง • รูปร่างเป็นรูปที่อยู่ในระนาบสองมิติ • มีพื้นที่ • เมธอด getArea() ใช้คำนวณหาพื้นที่ของรูปร่าง • มีสี • public enum Color { Red, Green, Blue } • เมธอด getColor()
คลาสรูปร่าง public enum Color{ Red, Green, Blue } public class Shape { private Color color; public Shape() { color = Color.Red; } public double getArea() { return 0; } public void setColor(Color c) { color = c; } public Color getColor() { return color; } }
ทดสอบคลาสรูปร่าง public class TestShape { public static void main(String[] args) { Shape s1 = new Shape(); System.out.println(s1.getColor()); System.out.println(s1.getArea()); Shape s2 = new Shape(); s2.setColor(Color.Blue); System.out.println(s2.getColor()); System.out.println(s2.getArea()); } }
คลาสสี่เหลี่ยมผืนผ้า class Rectangle extends Shape{ private double width; private double height; public Rectangle(int w, int h){ width = w; height = h; } public double getWidth(){ return width; } public double getHight(){ //ควรเติมอะไรตรงนี้ } }
คลาสสี่เหลี่ยมผืนผ้า class Rectangle extends Shape{ public double getArea() { return width * height; } … }
คลาสสี่เหลี่ยมผืนผ้า class Rectangle extends Shape{ public String toString(){ String str = “Rectangle”; str += “color = “ +getColor(); str += “width = “ +width; str += “height = “ +height; str += “area = “ +getArea(); return str; } }
ทดสอบคลาสสี่เหลี่ยม class TestShape1 { public static void main(String[] args) { Rectangle r = new Rectangle(3,4); System.out.println(r); System.out.println(r.toString()); } }
เมธอด toString() public class Rectangle extends Shape { ... public String toString() { String str = "Rectangle"; str += " color=" + getColor(); str += " width=" + width; str += " height=" + height; str += " area=" + getArea(); return str; } }
เมธอด toString() • เป็นเมธอดที่ถูกโอเวอร์ไรด์จากคลาส Object
คลาส Object • แม่ของทุกคลาส • เมธอดที่น่าสนใจ • toString() //ส่งค่าสตริงต่าง ๆ ในวัตถุที่สนใจ • equals() //ใช้เปรียบเทียบวัตถุ • clone() //ใช้โคลนนิ่งวัตถุ ตัวโคลนจะมีลักษณะเหมือนกับตัวจริงทุกประการ • hashCode() // จะส่งจำนวนเต็มที่เป็นรหัสแฮส รหัสใช้สำหรับการค้นหาอย่างรวดเร็ว
เมธอด equals() public boolean equals(Object otherObject) { if (otherObject instanceof Rectangle) { Rectangle otherRect = (Rectangle) otherObject; boolean equalWidth = width == otherRect.width; boolean equalHeight = height == otherRect.height; return equalWidth && equalHeight; } return false; }
เมธอด hashCode() • จะส่งจำนวนเต็มที่เป็นรหัสแฮช เพื่อการค้นหาข้อมูลที่รวดเร็ว public int hashCode() { return (int) (width + height * 17); }
เมธอด clone() สร้างวัตถุที่เหมือนกับวัตถุที่ได้รับข้อความ public Object clone() { Rectangle clone = new Rectangle(width, height); return clone; }
ทดสอบเมธอดที่โอเวอร์ไรด์จากคลาส Object public class TestRectangle3 { public static void main(String[] args) { Rectangle r1 = new Rectangle(2, 5); System.out.println(r1); System.out.println(r1.hashCode()); Rectangle r2 = new Rectangle(5, 2); System.out.println(r1.equals(r2)); Rectangle r3 = (Rectangle) r1.clone(); System.out.println(r1.equals(r3)); } }
สรุปเมธอดในคลาสสี่เหลี่ยมผืนผ้าสรุปเมธอดในคลาสสี่เหลี่ยมผืนผ้า
คลาสสี่เหลี่ยมจัตุรัสคลาสสี่เหลี่ยมจัตุรัส Public class Rectangle extends Shape{ public Rectangle(double w, double h){ …. } } public class Square extends Rectangle { public Square( double w) { super(w,w); } ... } เรียกใช้คอนสตรักเตอร์ในคลาส Rectangle
Super(); • super() หมายถึง การเรียกใช้คอนสตรักเตอร์ในคลาสแม่ • จากตัวอย่าง super(w,w) คือการเรียกใช้ Rectangle(double w, double h); • สาเหตุที่ใช้คำว่า super เพราะบางครั้งนิยมเรียกคลาสพื้นฐาน (คลาสแม่) ว่า super class และเรียกคลาสที่สืบทอด (คลาสลูก) ว่า subclass
คลาสสี่เหลี่ยมจัตุรัสคลาสสี่เหลี่ยมจัตุรัส public class Square extends Rectangle { public Square(double w){ super(w,w) } public String toString() { String str = "Rectangle"; str += " color=" + getColor(); str += " width=" + getWidth(); str += " area=" + getArea(); return str; } } เรียกจากคลาส Rectangle เรียกจากคลาส Shape เรียกจากคลาส Rectangle เรียกจากคลาส Rectangle
การห้ามสืบทอด • ไม่สามารถถูกสืบทอดได้ public final class Square ไฟนอลคลาส Public class SquareChild extends Square คอมไพล์ไม่ผ่าน