โดยส่วนตัวแล้วคลาสที่เรียกว่าในการเขียนโปรแกรมเป็นแนวคิดเดียวกับคลาสในโลกแห่งความเป็นจริงที่จัดประเภทวัตถุ แต่พวกเขาจะยืมในการเขียนโปรแกรม คลาสแสดงถึงสิ่งต่าง ๆ ที่มีชุดของ commonalities และการดำเนินการหรือการกระทำเดียวกันซึ่งเป็นประเภทข้อมูลที่เป็นนามธรรมในการเขียนโปรแกรม แต่ละบุคคล (ในโลกแห่งความเป็นจริง) และตัวแปรอินสแตนซ์ (สำหรับการเขียนโปรแกรม) เป็นวัตถุ
คลาสคือการแสดงคุณสมบัติทั่วไป (คุณลักษณะและการดำเนินงาน) ของวัตถุบางอย่างในโลกแห่งความเป็นจริงและวัตถุเป็นตัวอย่างของคลาส
คุณลักษณะของคลาส: เป็นตัวย่อของคุณลักษณะคงที่ของคลาสซึ่งหมายถึงข้อมูลต่าง ๆ ที่มีอยู่ในชั้นเรียนเช่นตัวแปรหรือวัตถุคลาสอื่น ๆ
บริการคลาส: เรียกว่าฟังก์ชันสมาชิกหรือวิธีการ
รูปแบบคำจำกัดความของคลาสใน Java มีดังนี้:
[Modifier] ชื่อคลาสคลาส [ขยายคลาสพาเรนต์] [ใช้ชื่ออินเตอร์เฟส] {คลาสสมาชิกตัวแปรคลาสประกาศวิธีการประกาศวิธีการประกาศ}}พูดคุยเกี่ยวกับแต่ละส่วนของรายละเอียด:
ก่อนที่คำหลักของคลาสตัวดัดแปลงคลาสจะแบ่งออกเป็นสามประเภท: การปรับเปลี่ยนการเข้าถึงระดับสาธารณะคลาสสาธารณะตัวดัดแปลงสุดท้าย (ตัวระบุคลาสสุดท้าย) และตัวดัดแปลงนามธรรม (ตัวระบุคลาสนามธรรม)
ในหมู่พวกเขาตัวดัดแปลงการอนุญาตสามารถเป็นสาธารณะหรือเริ่มต้น (เช่นว่างเปล่าไม่มีอะไรบ่งบอกว่ามันถูกกำหนดให้เป็นมิตร) และสาธารณะหมายความว่าชั้นเรียนสามารถใช้และเข้าถึงได้ทุกที่ (ตราบใดที่โปรแกรมสามารถค้นหาตำแหน่งของชั้นเรียน) ไม่ว่าจะอยู่ในแพ็คเกจเดียวกันหรือในแพ็คเกจที่แตกต่างกัน โปรดทราบว่าสิ่งนี้แตกต่างจาก C ++ C ++ ไม่มีตัวปรับเปลี่ยนเพื่อ จำกัด สิทธิ์การเข้าถึงในชั้นเรียน แต่มีสิทธิ์ในการเข้าถึงเพื่อรับความสัมพันธ์ระหว่างคลาส นอกจากนี้พวกเขาทั้งหมดมีสิทธิ์ในการเข้าถึงคุณลักษณะและวิธีการของคลาส การอนุญาตการเข้าถึงเริ่มต้น (เช่นที่กำหนดเป็นมิตร) หมายความว่าสามารถอ้างอิงและเข้าถึงได้โดยคลาสในแพ็คเกจเดียวกัน แต่ไม่สามารถเข้าถึงและอ้างอิงโดยคลาสในแพ็คเกจอื่น ๆ แม้ว่าจะนำเข้าก็ตาม
มันจะถูกกล่าวถึงในภายหลัง: เมื่อตัวปรับเปลี่ยนเริ่มต้นของแอตทริบิวต์คลาสและวิธีการใช้มันก็แสดงว่าสามารถอ้างอิงและเข้าถึงโดยคลาสในแพ็คเกจเดียวกันเท่านั้น
ไม่อนุญาตให้มีการสืบทอดหลายครั้งใน Java ซึ่งแตกต่างจาก C ++ เพื่อชดเชยข้อบกพร่องนี้ Java ได้แนะนำแนวคิดของอินเทอร์เฟซ
ในคำจำกัดความของคลาสข้างต้นร่างกายชั้นเรียนส่วนใหญ่มีเนื้อหาเฉพาะของคลาสรวมถึงคุณลักษณะของคลาสและวิธีการของคลาส คุณสมบัติของคลาสอาจเป็นตัวแปรหรืออินสแตนซ์ของคลาสบางคลาส หากเป็นอินสแตนซ์ของคลาสก็สามารถกำหนดได้ดังนี้:
[modifier] ชื่อคลาสชื่อวัตถุ = ชื่อคลาสใหม่ (รายการพารามิเตอร์);
เมื่อประกาศวัตถุและตัวแปรที่ซับซ้อนคุณไม่สามารถใช้การสร้างระหว่างการประกาศ แต่สามารถสร้างขึ้นในตัวสร้างในอนาคต
วิธีการที่กำหนดไว้ในชั้นเรียนมักจะเล่นสองบทบาท: หนึ่งคือการดำเนินการต่าง ๆ รอบ ๆ คุณลักษณะของชั้นเรียน; อีกอย่างคือการแลกเปลี่ยนข้อมูลการส่งข้อความและการดำเนินการอื่น ๆ ด้วยคลาสหรือวัตถุอื่น ๆ
ไวยากรณ์สำหรับการประกาศวิธีการใน Java มีดังนี้:
[modifier] ชื่อประเภทค่าวิธีการส่งคืนชื่อเมธอด (รายการพารามิเตอร์) โยนชื่อข้อยกเว้น 1, ชื่อข้อยกเว้น 2, … {วิธีการ: การประกาศตัวแปรท้องถิ่น; ลำดับคำสั่ง;}วิธีการคลาสหรือที่เรียกว่าฟังก์ชั่นสมาชิกใช้เพื่อระบุการดำเนินการบนแอตทริบิวต์คลาสและใช้ฟังก์ชั่นภายในของคลาส พวกเขายังเป็นหน้าต่างสำคัญสำหรับชั้นเรียนที่จะโต้ตอบกับโลกภายนอก
โปรแกรมเมอร์ Java มุ่งเน้นไปที่การสร้างประเภทที่ผู้ใช้กำหนดเรียกว่าคลาส คลาสเรียกอีกอย่างว่าโปรแกรมเมอร์ที่กำหนด แต่ละคลาสมีข้อมูลและชุดของวิธีการจัดการข้อมูล ส่วนข้อมูลในคลาสเรียกว่าตัวแปรอินสแตนซ์ อินสแตนซ์ของประเภทที่ผู้ใช้กำหนด (เช่นคลาส) เรียกว่าวัตถุ
วัตถุเป็นอินสแตนซ์ของคลาส คลาสเป็นนามธรรมของวัตถุประเภทเดียวกันและเทมเพลตสำหรับการสร้างวัตถุ การสร้างวัตถุในโปรแกรมจะเปิดพื้นที่ในหน่วยความจำรวมถึงคุณสมบัติและวิธีการของวัตถุ สร้างวัตถุโดยใช้ตัวดำเนินการคำหลักใหม่
ตัวสร้าง (สามารถเปรียบเทียบกับ C ++ ซึ่งเกือบจะเหมือนกับ C ++)
สร้างตัวสร้างของคุณเอง
•ชื่อของตัวสร้างและชื่อของคลาสเหมือนกัน เมื่อสร้างวัตถุของคลาสพนักงานตัวสร้างนี้จะเริ่มต้นและฟิลด์อินสแตนซ์ได้รับการกำหนดค่าเริ่มต้น ใน Java คำจำกัดความและการเริ่มต้นเป็นหนึ่งเดียว - ทั้งคู่เป็นสิ่งที่ขาดไม่ได้
ตัวอย่างเช่นเมื่อสร้างอินสแตนซ์ของคลาสพนักงานด้วยรหัสต่อไปนี้
Newemployee ("James Bond", 100000,1950,1,1);
ลักษณะของตัวสร้างคือ:
(1) ตัวสร้างและคลาสมีชื่อเดียวกัน
(2) คลาสสามารถมีตัวสร้างหลายตัว
(3) ตัวสร้างสามารถมีพารามิเตอร์ 0, 1 หรือมากกว่า
(4) ตัวสร้างไม่มีค่าส่งคืน
(5) ตัวสร้างจะถูกเรียกด้วยตัวดำเนินการใหม่เสมอ
บทบาทของตัวสร้าง
(1) การเริ่มต้นวัตถุ
(2) แนะนำความยืดหยุ่นมากขึ้น (การกำหนดตัวแปรหรือการดำเนินการที่ซับซ้อนมากขึ้น)
(3) ตัวสร้างไม่สามารถกำหนดใน Java
ตัวสร้างไม่สามารถกำหนดใน Java และระบบจะสร้างตัวสร้างเริ่มต้นโดยอัตโนมัติสำหรับระบบ ชื่อของตัวสร้างนี้เหมือนกับชื่อคลาสไม่มีพารามิเตอร์อย่างเป็นทางการและไม่ได้ดำเนินการใด ๆ
ภาพรวมวิธีการ
โปรแกรม Java ประกอบด้วยคำจำกัดความของคลาสและคลาสมีสองส่วน: คุณสมบัติและวิธีการ คลาสคำอธิบายแอตทริบิวต์คืออะไรและคลาสคำอธิบายวิธีการทำคืออะไร วัตถุใด ๆ มีหน่วยความจำอิสระในการจัดเก็บคุณสมบัติ วัตถุทั้งหมดของคลาสแชร์วิธีที่เก็บไว้ในหน่วยความจำ
กล่าวอีกนัยหนึ่ง: วิธีการเป็นองค์ประกอบหลักของคลาส ในชั้นเรียนบทบาทของโปรแกรมจะสะท้อนให้เห็นในวิธีการ
วิธีการคือการสร้างรูทีนย่อยที่มีชื่อโดย Java วิธีหลักและวิธีย่อยหลายวิธี วิธีการหลักเรียกวิธีการอื่นและวิธีอื่น ๆ สามารถเรียกกันและวิธีเดียวกันสามารถเรียกได้ตลอดเวลาโดยวิธีหนึ่งหรือมากกว่าหนึ่งวิธี
การกำหนดวิธีอื่นในวิธีหนึ่งจะสร้างข้อผิดพลาดทางไวยากรณ์
(1) เป็นการดีที่สุดที่จะหลีกเลี่ยงตัวแปรอินสแตนซ์ตัวแปร "หน้ากาก" สามารถทำได้โดยไม่ต้องใช้ตัวระบุชื่อเดียวกันในชั้นเรียน พารามิเตอร์ในการโทรวิธีใช้เพื่อส่งค่าตัวเลขและการอ้างอิงและวิธีการสามารถเรียกได้ในซ้อนและซ้ำ
(2) หากระบุประเภทค่าคืนที่ไม่ได้รับการเรียกร้องในตัวถังวิธีการจะต้องรวมคำสั่งคืนเพื่อให้แน่ใจว่ามีค่าส่งคืนในกรณีใด ๆ และคำสั่งส่งคืนไม่สามารถตามด้วยนิพจน์ใด ๆ ;
โครงสร้างพื้นฐานของโปรแกรม Java มีดังนี้:
แนะนำห้องสมุดคลาส Java; กำหนดคลาสผู้ใช้ 1 {กำหนดตัวแปรหรือวัตถุหลายอย่างของคลาส 1: กำหนดวิธี 1 ของคลาส 1; กำหนดวิธีที่ 2 ของคลาส 1; …กำหนดวิธี M1 ของคลาส 1; } กำหนดคลาสผู้ใช้ 2 {กำหนดตัวแปรหรือวัตถุหลายตัวของคลาส 2: กำหนดวิธี 1 ของคลาส 2; กำหนดวิธีที่ 2 ของคลาส 2; …กำหนดวิธี M2 ของคลาส 2}Java แนะนำแนวคิดของ "การควบคุมการเข้าถึงการควบคุม" ที่อนุญาตให้ผู้สร้างห้องสมุดประกาศสิ่งที่โปรแกรมเมอร์ไคลเอ็นต์สามารถใช้งานได้และสิ่งที่ไม่สามารถใช้ได้
การควบคุมการเข้าถึงระดับนี้อยู่ระหว่างช่วงของ "การเข้าถึงสูงสุด" และ "การเข้าถึงขั้นต่ำ" รวมถึง: สาธารณะ, "เริ่มต้น" (ไม่มีคำหลัก), ป้องกันและเป็นส่วนตัว รายการต่อไปนี้อธิบายถึงความหมายของตัวดัดแปลงการควบคุมการเข้าถึง:
อักขระควบคุมการเข้าถึงสาธารณะ
สำหรับชั้นเรียน:
มีตัวควบคุมการเข้าถึงเพียงตัวเดียวสำหรับชั้นเรียนใน Java: สาธารณะนั่นคือสาธารณะ ชั้นเรียนถูกประกาศว่าเป็นคลาสสาธารณะซึ่งระบุว่าสามารถเข้าถึงและอ้างอิงได้โดยคลาสอื่น ๆ ทั้งหมด การเข้าถึงและการอ้างอิงที่นี่หมายถึงชั้นเรียนที่มองเห็นได้และใช้งานได้โดยรวม ส่วนอื่น ๆ ของโปรแกรมสามารถสร้างวัตถุของคลาสนี้ตัวแปรสมาชิกเข้าถึงที่มองเห็นได้ภายในชั้นเรียนและเรียกวิธีการที่มองเห็นได้
ชั้นเรียนสามารถมองเห็นได้ในส่วนอื่น ๆ ของโปรแกรมโดยรวมและไม่ได้แสดงว่าคุณสมบัติและวิธีการทั้งหมดในชั้นเรียนสามารถมองเห็นได้ในส่วนอื่น ๆ ของโปรแกรม อดีตเป็นเพียงเงื่อนไขที่จำเป็นสำหรับหลัง ไม่ว่าจะเป็นคุณสมบัติและวิธีการของคลาสสามารถเข้าถึงได้โดยคลาสอื่น ๆ ทั้งหมดขึ้นอยู่กับอักขระควบคุมการเข้าถึงของคุณสมบัติและวิธีการเหล่านี้
ใช้สำหรับคุณสมบัติในชั้นเรียน:
คุณลักษณะในชั้นเรียนที่แก้ไขด้วยสาธารณะเรียกว่าคุณลักษณะสาธารณะ หากคลาสนี้เป็นคลาสสาธารณะก็สามารถเข้าถึงได้โดยคลาสอื่น ๆ ทั้งหมด
การควบคุมการเข้าถึงเริ่มต้น
ใช้สำหรับชั้นเรียน
หากคลาสไม่มีอักขระควบคุมการเข้าถึงหมายความว่ามีคุณสมบัติการควบคุมการเข้าถึงเริ่มต้น การควบคุมการเข้าถึงเริ่มต้นนี้กำหนดว่าคลาสสามารถเข้าถึงและอ้างอิงโดยคลาสในแพ็คเกจเดียวกันและไม่สามารถใช้โดยคลาสในแพ็คเกจอื่น ๆ คุณสมบัติการเข้าถึงนี้เรียกว่าการเข้าถึงแพ็คเกจ โดยการประกาศอักขระควบคุมการเข้าถึงของคลาสโครงสร้างโปรแกรมทั้งหมดสามารถชัดเจนและเข้มงวดลดการรบกวนระหว่างคลาสและข้อผิดพลาดที่เป็นไปได้
ใช้สำหรับแอตทริบิวต์คลาส
หากคุณสมบัติและวิธีการภายในชั้นเรียนไม่ได้ถูก จำกัด ด้วยสัญลักษณ์ควบคุมการเข้าถึงพวกเขายังระบุว่าพวกเขาคือการเข้าถึงแพ็คเก็ต
3 ตัวละครควบคุมการเข้าถึงส่วนตัวส่วนตัว
แอตทริบิวต์หรือวิธีการที่แก้ไขด้วยส่วนตัวสามารถเข้าถึงและแก้ไขได้โดยคลาสเท่านั้นและไม่สามารถรับและอ้างอิงได้โดยคลาสอื่น ๆ รวมถึงคลาสย่อยของคลาส
1). ตัวอย่างเช่นข้อมูลส่วนตัวมีสามฟิลด์อินสแตนซ์ซึ่งมีข้อมูลที่ดำเนินการภายในอินสแตนซ์ของคลาสพนักงาน
ชื่อสตริงส่วนตัว;
เงินเดือนสองเท่าส่วนตัว
วันที่จ้างส่วนตัว
คำหลักส่วนตัวใช้เพื่อให้แน่ใจว่าฟิลด์อินสแตนซ์เหล่านี้สามารถเข้าถึงได้โดยคลาสพนักงานเท่านั้น
2). วิธีการส่วนตัวเมื่อใช้คลาสเราทำให้เขตข้อมูลทั้งหมดเป็นส่วนตัวเนื่องจากข้อมูลสาธารณะเป็นอันตราย สถานการณ์กับวิธีการคืออะไร? แม้ว่าวิธีการส่วนใหญ่จะเป็นแบบสาธารณะ แต่ก็มีการใช้วิธีการส่วนตัวบ่อยครั้ง วิธีการเหล่านี้สามารถคั่นด้วยวิธีเดียวกันเท่านั้น
ในระยะสั้นสามารถเลือกวิธีส่วนตัวในกรณีต่อไปนี้:
(1) วิธีการเหล่านั้นที่ไม่เกี่ยวข้องกับผู้ใช้ของชั้นเรียน
(2) วิธีการเหล่านั้นที่ไม่ง่ายต่อการบำรุงรักษาหากการใช้งานของชั้นเรียนเปลี่ยนไป
ตัวควบคุมการควบคุมการเข้าถึงที่ได้รับการป้องกันการป้องกัน
ตัวแปรสมาชิกที่แก้ไขด้วยการป้องกันสามารถอ้างอิงได้สามประเภท: คลาสเองคลาสอื่น ๆ ในแพ็คเกจเดียวกับมันและคลาสย่อยของคลาสในแพ็คเกจอื่น ๆ วัตถุประสงค์หลักของการใช้ตัวดัดแปลงที่ได้รับการป้องกันคือการอนุญาตให้คลาสย่อยในแพ็คเกจอื่น ๆ เพื่อเข้าถึงคุณสมบัติเฉพาะของคลาสแม่
คำหลักที่ได้รับการป้องกันแนะนำให้เรารู้จักกับแนวคิดที่เรียกว่า "การสืบทอด" ซึ่งขึ้นอยู่กับคลาสที่มีอยู่และเพิ่มสมาชิกใหม่ให้กับมันโดยไม่ส่งผลกระทบต่อคลาสที่มีอยู่ - เราเรียกคลาสนี้ว่า "คลาสพื้นฐาน" หรือ "คลาสพื้นฐาน" นอกจากนี้ยังสามารถเปลี่ยนพฤติกรรมของสมาชิกที่มีอยู่ของชั้นเรียนนั้น สำหรับมรดกจากคลาสที่มีอยู่เราบอกว่าคลาสใหม่ของเรา "ขยาย" คลาสที่มีอยู่
ตัวควบคุมการเข้าถึงส่วนตัวที่ได้รับการป้องกันตัวละครส่วนตัวได้รับการปกป้อง
ส่วนตัวและได้รับการป้องกันใช้ตามลำดับเพื่อสร้างอักขระควบคุมการเข้าถึงที่สมบูรณ์: อักขระควบคุมการเข้าถึงการป้องกันส่วนตัว ตัวแปรสมาชิกที่แก้ไขด้วย Private -Protection สามารถเข้าถึงและอ้างอิงได้สองคลาสหนึ่งคือคลาสของตัวเองและอีกคลาสทั้งหมดเป็นคลาสย่อยทั้งหมดของคลาสไม่ว่าจะเป็นคลาสย่อยเหล่านี้อยู่ในแพ็คเกจเดียวกับคลาสหรือในแพ็คเกจอื่น ๆ
เมื่อเปรียบเทียบกับการป้องกันตัวดัดแปลงแบบส่วนตัวที่ป้องกันไม่ให้ไม่รวม subclasses ภายในแพ็คเกจเดียวกันจากขอบเขตที่เข้าถึงได้ทำให้ตัวแปรสมาชิกเป็นกรรมสิทธิ์มากขึ้นสำหรับชั้นเรียนที่มีความสัมพันธ์การสืบทอดที่ชัดเจนมากกว่าแพ็คเกจที่จัดกลุ่มเข้าด้วยกันอย่างอิสระ
ตัวดัดแปลงคงที่
คงที่เรียกว่าตัวดัดแปลงแบบคงที่ซึ่งปรับเปลี่ยนคุณสมบัติและวิธีการในชั้นเรียน
การใช้คำหลักคงที่สามารถตอบสนองความต้องการสองประการ:
(1) สถานการณ์หนึ่งคือคุณต้องการใช้พื้นที่จัดเก็บเพื่อบันทึกข้อมูลเฉพาะ - ไม่ว่าคุณต้องการสร้างวัตถุจำนวนเท่าใดคุณไม่ได้สร้างวัตถุเลย แอตทริบิวต์ที่แก้ไขโดยคงที่เรียกว่าคุณสมบัติคงที่และหนึ่งในคุณสมบัติที่สำคัญที่สุดของแอตทริบิวต์ประเภทนี้คือพวกเขาเป็นคุณลักษณะของคลาสไม่ใช่วัตถุเฉพาะของคลาสใด ๆ กล่าวอีกนัยหนึ่งสำหรับวัตถุเฉพาะของคลาสนี้คุณสมบัติคงที่เป็นหน่วยเก็บข้อมูลทั่วไป เมื่อวัตถุใด ๆ ของคลาสใด ๆ เข้าถึงได้จะได้รับค่าตัวเลขเท่ากัน เมื่อวัตถุใด ๆ ของคลาสใด ๆ ปรับเปลี่ยนมันก็กำลังดำเนินการในหน่วยหน่วยความจำเดียวกัน
(2) สถานการณ์อื่นคือเราต้องการวิธีพิเศษที่ไม่เกี่ยวข้องกับวัตถุใด ๆ ของคลาสนี้ กล่าวคือแม้ว่าจะไม่ได้สร้างวัตถุวิธีการที่สามารถเรียกได้โดยตรงโดยคลาสก็เป็นสิ่งจำเป็น
จุดประสงค์ที่สำคัญของการคงที่คือการช่วยให้เราเรียกวิธีการนั้นโดยไม่ต้องสร้างวัตถุ
ค่าคงที่
ตัวแปรคงที่หายาก อย่างไรก็ตามค่าคงที่คงที่เป็นเรื่องธรรมดา ตัวอย่างเช่นค่าคงที่คงที่ถูกกำหนดในคลาสคณิตศาสตร์:
คณิตศาสตร์ระดับสาธารณะ
{…สาธารณะคงที่สาธารณะสุดท้าย pi = 3.1.4159265358979323846666; …} วิธีการคงที่ประกาศว่าวิธีการคงที่มีความหมายอย่างน้อยสามประการ:
(1) เมื่อใช้วิธีนี้ชื่อคลาสควรใช้เป็นคำนำหน้าแทนที่จะเป็นชื่อวัตถุเฉพาะ
(2) วิธีการที่ไม่คงที่เป็นวิธีการที่เป็นของวัตถุ เมื่อวัตถุนี้ถูกสร้างขึ้นวิธีการของวัตถุจะมีเซ็กเมนต์รหัสเฉพาะของตัวเองในหน่วยความจำ ในขณะที่วิธีการคงที่เป็นของคลาสทั้งหมดและส่วนโค้ดในหน่วยความจำจะได้รับการจัดสรรและโหลดตามคำจำกัดความของคลาสและจะไม่เป็นเอกสิทธิ์ของวัตถุใด ๆ
(3) เนื่องจากวิธีการคงที่เป็นของคลาสทั้งหมดจึงไม่สามารถจัดการและประมวลผลตัวแปรสมาชิกที่เป็นของวัตถุที่แน่นอน แต่สามารถประมวลผลตัวแปรสมาชิกที่เป็นของทั้งคลาสทั้งหมด
5 วิธีหลัก
วิธีหลักไม่ได้ใช้การดำเนินการกับวัตถุใด ๆ ในความเป็นจริงเมื่อโปรแกรมเริ่มดำเนินการยังไม่มีวัตถุใดบ้าง วิธีการคงที่ถูกดำเนินการและวัตถุที่ต้องการโดยโปรแกรมจะถูกสร้างขึ้น
มันแจ้งให้แต่ละชั้นเรียนมีวิธีการหลัก นี่เป็นเคล็ดลับที่สะดวกมากในการเรียนการทดสอบหน่วย
บทคัดย่อเป็นตัวดัดแปลงนามธรรมที่สามารถใช้ในการปรับเปลี่ยนคลาสหรือวิธีการ
คลาสนามธรรม
เมื่อคลาสถูกประกาศว่าเป็นนามธรรมคลาสนี้เรียกว่าคลาสนามธรรม คลาสนามธรรมที่เรียกว่าเป็นคลาสที่ไม่มีวัตถุอินสแตนซ์คอนกรีต
เพื่อแก้ไขปัญหานี้ Java ให้กลไกที่เรียกว่า "วิธีนามธรรม" มันเป็นของวิธีการที่ไม่สมบูรณ์โดยมีเพียงการประกาศเพียงครั้งเดียวและไม่มีวิธีการ นี่คือไวยากรณ์ที่ใช้เมื่อประกาศวิธีนามธรรม:
บทคัดย่อโมฆะ x ();
วิธีนามธรรม
ในฐานะที่เป็นตัวดัดแปลงวิธีการคลาสบทคัดย่อประกาศวิธีนามธรรมที่มีเฉพาะส่วนหัวของวิธี แต่ไม่มีวิธีการเฉพาะร่างกายและการใช้งาน
จะเห็นได้ว่าวิธีนามธรรมมีเพียงการประกาศของส่วนหัวของวิธีการและ semicolon ถูกใช้เพื่อแทนที่คำจำกัดความของร่างกายวิธี: สำหรับการใช้งานเฉพาะของร่างกายวิธีการมันเสร็จสิ้นโดย subclasses ที่แตกต่างกันของคลาสปัจจุบันในคำจำกัดความคลาสที่เกี่ยวข้อง
ควรสังเกตว่าวิธีการนามธรรมทั้งหมดจะต้องมีอยู่ในคลาสนามธรรม
กลาง.
นอกเหนือจากวิธีการที่เป็นนามธรรมคลาสนามธรรมยังสามารถมีข้อมูลและวิธีการที่เป็นรูปธรรม
วิธีการนามธรรมเป็นแนวคิดที่สำคัญมากในภาษาการเขียนโปรแกรม Java คุณจะใช้มันหลายวิธีในอินเทอร์เฟซ
หมายเหตุ: ที่นี่เราต้องเปรียบเทียบและจดจำกับอินเทอร์เฟซ วิธีการในอินเทอร์เฟซเป็นวิธีนามธรรมทั้งหมด แน่นอนว่ายังมีคุณลักษณะในอินเทอร์เฟซและคุณสมบัติเฉพาะของพวกเขาจะถูกอธิบายในรายละเอียดในภายหลัง
คลาสสุดท้าย, แอตทริบิวต์สุดท้าย, วิธีสุดท้ายและ finalizer (ไม่มีตัวปรับเปลี่ยนสุดท้ายใน C ++)
สุดท้ายคือตัวดัดแปลงสุดท้ายซึ่งปรับเปลี่ยนคลาสคุณสมบัติและวิธีการ นอกจากนี้คำหลักของเทอร์มินัลนั้นคล้ายกับรอบสุดท้ายและจะถูกนำมาใช้ร่วมกัน
ชั้นสุดท้าย
หากคลาสได้รับการประกาศขั้นสุดท้ายหมายความว่ามันไม่สามารถหาคลาสย่อยใหม่และไม่สามารถสืบทอดเป็นคลาสหลักได้ ดังนั้นชั้นเรียนไม่สามารถประกาศได้ทั้งนามธรรมและสุดท้าย
คลาสที่กำหนดเป็นขั้นสุดท้ายมักจะเป็นคลาสที่มีฟังก์ชั่นพิเศษที่ใช้ในการทำฟังก์ชั่นมาตรฐานให้สมบูรณ์ การกำหนดคลาสเป็นขั้นสุดท้ายสามารถแก้ไขเนื้อหาแอตทริบิวต์และฟังก์ชั่นและสร้างความสัมพันธ์การแมปที่เสถียรด้วยชื่อคลาสของมันเพื่อให้มั่นใจว่าฟังก์ชั่นที่นำมาใช้เมื่ออ้างถึงคลาสนี้ถูกต้อง
คุณลักษณะสุดท้าย
ภาษาการเขียนโปรแกรมหลายภาษามีวิธีของตัวเองในการบอกคอมไพเลอร์ว่าข้อมูลบางอย่างเป็น "ค่าคงที่" ค่าคงที่ส่วนใหญ่จะใช้ในสองด้านต่อไปนี้:
(1) ค่าคงที่ระยะเวลาการรวบรวมมันจะไม่เปลี่ยนแปลง
(2) เราไม่ต้องการให้ค่าเริ่มต้นระหว่างการเปลี่ยนแปลงรันไทม์
ฟิลด์อินสแตนซ์สามารถกำหนดเป็นขั้นสุดท้าย (ไม่สามารถเปลี่ยนแปลงได้) ฟิลด์นี้จะต้องเริ่มต้นเมื่อสร้างวัตถุ นั่นคือจะต้องมั่นใจว่าค่าได้ถูกตั้งค่าก่อนที่จะสิ้นสุดของแต่ละตัวสร้าง มูลค่าของฟิลด์ไม่สามารถเปลี่ยนแปลงได้ในอนาคต
วิธีสุดท้าย
เหตุผลในการใช้วิธีสุดท้ายอาจเกิดจากการพิจารณาด้วยเหตุผลสองประการ
สิ่งแรกคือการ "ล็อค" วิธีการเพื่อป้องกันไม่ให้คลาสการสืบทอดใด ๆ เปลี่ยนความหมายดั้งเดิม เมื่อออกแบบโปรแกรมการปฏิบัตินี้สามารถนำมาใช้หากคุณต้องการพฤติกรรมของวิธีการที่จะไม่เปลี่ยนแปลงในระหว่างการสืบทอดและไม่สามารถเขียนทับหรือเขียนใหม่ได้
เหตุผลที่สองสำหรับการใช้วิธีสุดท้ายคือประสิทธิภาพของการดำเนินการโปรแกรม
เครื่องปลายทาง
ฟังก์ชั่นของ Terminator เป็นวิธีที่ดำเนินการเมื่อดึงวัตถุ คล้ายกับวิธีการที่ตัวสร้างจะดำเนินการเมื่อสร้างวัตถุ
ตัวอย่าง
ป้องกัน voidfinalize () {system.out.println (""); -ตัวดัดแปลงอื่น ๆ
ระเหย
หากแอตทริบิวต์ได้รับการแก้ไขโดยความผันผวนก็หมายความว่าแอตทริบิวต์นี้สามารถควบคุมและแก้ไขได้หลายเธรดในเวลาเดียวกัน
ซิงโครไนซ์
ส่วนใหญ่ใช้สำหรับการซิงโครไนซ์เธรด
พื้นเมือง
หมายความว่าวิธีการไม่ได้เขียนด้วยภาษา Java (เขียนไว้ใน C, C ++ และภาษาอื่น ๆ )
ข้อมูลบางอย่างที่พบออนไลน์: - หมวดหมู่ภายใน
พูดง่ายๆคือคลาสภายในเป็นคลาสในคลาสตัวอย่างเช่น:
คลาส A {ส่วนตัว int i; โมฆะส่วนตัว m () {} คลาส b {mm (int j) {i = j; m ();}}}ที่นี่ B คือคลาสภายในของ A ซึ่งโดดเด่นด้วยการเข้าถึงวิธีการส่วนตัวและคุณสมบัติส่วนตัวในคลาสภายนอก ตัวอย่างเช่นที่นี่ B สามารถเข้าถึงคุณสมบัติส่วนตัว i และวิธีการส่วนตัว m () ใน A.
คุณสมบัติที่สำคัญที่สุดของการเขียนโปรแกรมเชิงวัตถุคือ encapsulation (เรียกอีกอย่างว่านามธรรม), การสืบทอดและ polymorphism ในฐานะที่เป็นภาษาการเขียนโปรแกรมเชิงวัตถุ Java มีข้อได้เปรียบของตัวเองในเรื่องนี้:
"การสืบทอดเป็นรูปแบบของการใช้ซอฟต์แวร์ซ้ำซึ่งมีประสิทธิภาพในการลดความซับซ้อนของซอฟต์แวร์การสืบทอดเป็นคุณสมบัติของภาษาการเขียนโปรแกรมเชิงวัตถุภาษาที่ใช้วัตถุ แต่ไม่มีการสืบทอดเป็นภาษาที่ใช้วัตถุ แต่ไม่ใช่ภาษาที่มุ่งเน้นวัตถุนี่คือความแตกต่างระหว่างทั้งสอง"
ความสัมพันธ์ระหว่างการสืบทอดระหว่างชั้นเรียนคือการจำลองโดยตรงของความสัมพันธ์ทางพันธุกรรมในโลกแห่งความเป็นจริง มันแสดงถึงการเชื่อมต่อที่แท้จริงระหว่างคลาสและการแบ่งปันแอตทริบิวต์และการดำเนินการนั่นคือคลาสย่อยสามารถติดตามคุณสมบัติบางอย่างของคลาสแม่ (คลาสที่สืบทอดมา) แน่นอนคลาสย่อยสามารถมีคุณสมบัติและการดำเนินงานอิสระของตนเอง
มรดกเป็นรูปแบบของการใช้ซอฟต์แวร์ซ้ำ คลาสใหม่ถูกสร้างขึ้นโดยคลาสที่มีอยู่และคุณลักษณะและพฤติกรรมใหม่จะถูกเพิ่มโดยการรักษาคุณสมบัติและพฤติกรรมของพวกเขาและการปรับเปลี่ยนประสิทธิภาพตามข้อกำหนดของคลาสใหม่ หากชั้นเรียนเด็กสืบทอดเฉพาะจากคลาสหลักเดียวจะเรียกว่าการสืบทอดเดี่ยว หากชั้นเรียนเด็กสืบทอดมาจากคลาสแม่มากกว่าหนึ่งระดับมันจะเรียกว่าหลายเส้นผ่าศูนย์กลาง โปรดทราบว่า Java ไม่สนับสนุนการสืบทอดหลายครั้ง แต่สนับสนุนแนวคิดของ "อินเตอร์เฟส" อินเตอร์เฟสอนุญาตให้ Java ได้รับข้อได้เปรียบหลายประการของการสืบทอดหลายครั้งและละทิ้งข้อเสียที่สอดคล้องกัน หมายเหตุ: C ++ รองรับหลายมรดก
คำจำกัดความของความสัมพันธ์การสืบทอด:
[Modifier] ชื่อคลาสย่อยของคลาสขยายชื่อคลาสพาเรนต์, ชื่อคลาสแม่ 2 ชื่อ 2
ชื่อคลาสแม่ตามมาขยาย
คำหลักใช้เพื่อระบุคลาสย่อยของคลาสปัจจุบันที่มีอยู่แล้วและมีความสัมพันธ์ในการสืบทอด
กำหนดสองคลาสย่อยของพนักงานชั้นพนักงาน:
หมวดหมู่พนักงานทั่วไป: Commonemployee
หมวดหมู่หัวหน้างาน: ManagerEmployee
มีสองแง่มุมหลักของการสืบทอดคลาสย่อยจากคลาสแม่:
(1) มรดกของคุณลักษณะ ตัวอย่างเช่น บริษัท คือชั้นเรียนหลักและ บริษัท มีชื่อที่อยู่ผู้จัดการพนักงาน ฯลฯ ซึ่งเป็นโครงสร้างทั้งหมด
(2) วิธีการสืบทอด ชั้นเรียนผู้ปกครองกำหนดการดำเนินงานหลายอย่างเช่น บริษัท ที่ต้องการโครงการกำไรการแต่งตั้งผู้จัดการพนักงานรับสมัคร ฯลฯ และ บริษัท ย่อยจะสืบทอดการกระทำเหล่านี้ด้วย;
classcommonemployeeextends พนักงาน // subclass 1: {intm_managerno; // define แอตทริบิวต์คลาส m_managerno, เป็นตัวแทนหมายเลขหัวหน้าพนักงาน} classmanageMployeextends พนักงาน // subclass 2: {intm_secretaryno; คุณลักษณะการสืบทอดและการซ่อน
แม้ว่าคลาสพนักงานจะเป็นคลาสหลัก แต่ก็ไม่ได้หมายความว่ามันมีฟังก์ชั่นมากกว่านี้เพียงเพราะเป็นคลาสหลัก ในทางตรงกันข้าม sub-analogs มีฟังก์ชั่นมากกว่าคลาสแม่ของพวกเขา เนื่องจาก subclass เป็นส่วนขยายของคลาสแม่คุณลักษณะและวิธีการที่คลาสแม่ไม่ได้ถูกเพิ่ม (1) subclass ไม่สามารถเข้าถึงสมาชิกส่วนตัวของคลาสแม่ แต่คลาสย่อยสามารถเข้าถึงสาธารณะของคลาสแม่
(2) การเข้าถึงที่ได้รับการป้องกันเป็นระดับกลางป้องกันระหว่างการเข้าถึงภาครัฐและเอกชน
(3) เนื่องจากสมาชิกชั้นพาเรนต์ที่สืบทอดมาไม่ได้อยู่ในการประกาศ subclaration สมาชิกเหล่านี้จึงมีอยู่ในคลาสย่อย
ที่นี่เราต้องแยกแยะระหว่างการสืบทอดการเขียนทับและการโอเวอร์โหลดแนวคิดที่สับสนหลายประการ:
เฉพาะในระดับแนวคิดของวิธีการสองแนวคิดนี้สามารถสับสนได้ง่าย:
วิธีการสืบทอด
สำหรับวัตถุ subclass สามารถใช้วิธีการจากคลาสแม่ แม้ว่าวิธีการเหล่านี้จะไม่ได้กำหนดไว้อย่างชัดเจนในคลาสย่อยพวกเขาจะได้รับการสืบทอดจากคลาสแม่โดยอัตโนมัติ
วิธีการครอบคลุมวิธีการ
วิธีการแทนที่หมายถึง: วิธีการที่กำหนดวิธีการที่มีชื่อเดียวกันเพื่อเขียนทับคลาสแม่ซึ่งเป็นการใช้เทคโนโลยี polymorphic เมื่อวิธีการคลาสแม่ถูกเขียนทับในคลาสเด็กมักจะเป็นรุ่นคลาสเด็กที่เรียกรุ่นคลาสแม่และทำงานเพิ่มเติม
มีหลายสิ่งที่ควรทราบ ที่นี่ฉันพูดถึงเรื่องนี้เป็นหลักและสุดยอด มีสิ่งนี้ใน C ++ (และแนวคิดคล้ายกับใน Java) แต่ไม่มี Super
สิ่งนี้แสดงถึงวัตถุปัจจุบันเองและสิ่งนี้แสดงถึงการอ้างอิงถึงวัตถุปัจจุบัน มันสามารถเข้าใจได้ว่าเป็นชื่ออื่นของวัตถุ สิ่งนี้ช่วยให้คุณเรียกวิธีการและคุณสมบัติของวัตถุปัจจุบัน
ตัวอย่างเช่น: this.getName () และ getName () เหมือนกันในชั้นเรียน
Super แสดงถึงวัตถุคลาสแม่แบบโดยตรงของวัตถุปัจจุบันและเป็นวิธีการอ้างอิงโอเวอร์โหลดของวัตถุคลาสแม่ของวัตถุปัจจุบัน
คำจำกัดความของการโอเวอร์โหลด: วิธีการสามารถกำหนดด้วยชื่อวิธีเดียวกัน แต่ตารางพารามิเตอร์ที่แตกต่างกัน (หมายเลขประเภทหรือลำดับของพารามิเตอร์ในตารางพารามิเตอร์มีค่าที่แตกต่างกัน) ซึ่งเรียกว่าวิธีการโอเวอร์โหลด
•การโอเวอร์โหลด: การโอเวอร์โหลดเกิดขึ้นเมื่อหลายวิธีมีชื่อเดียวกันและมีพารามิเตอร์ที่แตกต่างกัน คอมไพเลอร์ต้องเลือกวิธีการโทร มันเลือกวิธีที่ถูกต้องโดยการเปรียบเทียบประเภทพารามิเตอร์ในส่วนหัววิธีการต่าง ๆ กับประเภทของค่าที่ใช้ในการเรียกวิธีการเฉพาะ
Polymorphism ช่วยให้การประมวลผลของตัวแปรที่มีอยู่และคลาสที่เกี่ยวข้องในรูปแบบแบบครบวงจรทำให้ง่ายต่อการเพิ่มคุณสมบัติใหม่ในระบบ ที่นี่การโพสต์ข้อมูลที่คุณพบทางออนไลน์สามารถชี้แจงความหลากหลายและปัญหามรดกที่ต้องการความสนใจเป็นพิเศษในการสืบทอด:
ความหลากหลายของชวา
การเขียนโปรแกรมเชิงวัตถุมีสามลักษณะคือการห่อหุ้มการสืบทอดและความหลากหลาย
Encapsulation ซ่อนกลไกการใช้งานภายในของชั้นเรียนเพื่อให้โครงสร้างภายในของคลาสสามารถเปลี่ยนแปลงได้โดยไม่ส่งผลกระทบต่อผู้ใช้ในขณะที่ปกป้องข้อมูล
การสืบทอดคือการใช้รหัสคลาสแม่อีกครั้งในขณะที่เตรียมพร้อมสำหรับการดำเนินการของ polymorphism polymorphism คืออะไร?
วิธีการเขียนใหม่การโอเวอร์โหลดและการเชื่อมต่อแบบไดนามิกเป็นความหลากหลาย หนึ่งในเหตุผลที่ Java แนะนำแนวคิดของ polymorphism คือมันแตกต่างจาก C ++ ในแง่ของการสืบทอดคลาส หลังอนุญาตให้มีการสืบทอดหลายครั้งซึ่งนำมาซึ่งฟังก์ชั่นที่ทรงพลังมาก แต่ความสัมพันธ์การสืบทอดที่ซับซ้อนก็นำปัญหามาสู่นักพัฒนา C ++ ได้มากขึ้น เพื่อหลีกเลี่ยงความเสี่ยง Java อนุญาตให้รับมรดกเดี่ยวเท่านั้นและมีความสัมพันธ์ IS-A ระหว่างคลาสที่ได้รับและคลาสพื้นฐาน (เช่น "แมว" คือ "สัตว์") แม้ว่าการทำเช่นนี้จะช่วยให้มั่นใจได้ถึงความเรียบง่ายและความชัดเจนของความสัมพันธ์ในการสืบทอด แต่ก็จะมีข้อ จำกัด การทำงานที่ดีอย่างหลีกเลี่ยงไม่ได้ ดังนั้น Java จึงแนะนำแนวคิดของ polymorphism เพื่อชดเชยข้อบกพร่องนี้ นอกจากนี้คลาสนามธรรมและอินเทอร์เฟซยังเป็นวิธีที่สำคัญในการแก้ข้อ จำกัด ของกฎระเบียบการสืบทอดเดี่ยว ในเวลาเดียวกัน polymorphism ก็เป็นสาระสำคัญของการเขียนโปรแกรมเชิงวัตถุ
เพื่อให้เข้าใจถึงความหลากหลายคุณต้องรู้ก่อนว่า "การเปลี่ยนแปลงที่สูงขึ้น" คืออะไร
ฉันกำหนดแมวย่อยซึ่งสืบทอดคลาสสัตว์และหลังคืออดีตคือคลาสหลัก ฉันสามารถผ่านได้
แมว C = แมวใหม่ ();
อินสแตนซ์วัตถุแมวไม่ยากที่จะเข้าใจ แต่เมื่อฉันนิยามเช่นนี้:
สัตว์ A = แมวใหม่ ();
สิ่งนี้หมายความว่าอย่างไร?
มันง่ายหมายความว่าฉันกำหนดประเภทสัตว์อ้างอิงไปยังวัตถุประเภทแมวที่สร้างขึ้นใหม่ เนื่องจากแมวได้รับการสืบทอดมาจากสัตว์ระดับพ่อแม่การอ้างอิงถึงประเภทสัตว์สามารถชี้ไปที่วัตถุประเภทแมว แล้วจุดนี้คืออะไร? เนื่องจากคลาสย่อยคือการปรับปรุงและขยายไปยังคลาสหลักคลาสย่อยโดยทั่วไปจะมีประสิทธิภาพมากกว่าคลาสแม่ในฟังก์ชั่นและคุณลักษณะของพวกเขามีความโดดเด่นกว่าคลาสแม่
การกำหนดการอ้างอิงไปยังประเภทคลาสพาเรนต์ชี้ไปที่วัตถุที่เป็น subclassed ไม่เพียง แต่สามารถใช้ฟังก์ชั่นที่ทรงพลังของคลาสย่อยเท่านั้น แต่ยังแยกส่วนร่วมของคลาสแม่ด้วย
ดังนั้นการอ้างอิงถึงประเภทคลาสแม่สามารถเรียกคุณสมบัติและวิธีการทั้งหมดที่กำหนดไว้ในคลาสหลักและเป็นสิ่งที่ช่วยไม่ได้สำหรับวิธีการที่กำหนดไว้ในคลาสเด็ก แต่ไม่ได้อยู่ในคลาสหลัก
ในเวลาเดียวกันวิธีการในคลาสหลักสามารถเรียกได้โดยการอ้างอิงถึงประเภทคลาสแม่ถ้ามันถูกกำหนดไว้ในคลาสพาเรนต์ แต่ไม่ได้แทนที่ในคลาสเด็ก
สำหรับวิธีการที่กำหนดไว้ในคลาสหลักหากวิธีการเขียนใหม่ในคลาสเด็กการอ้างอิงถึงประเภทคลาสแม่จะเรียกวิธีนี้ในคลาสลูกซึ่งเป็นการเชื่อมต่อแบบไดนามิก
ดูโปรแกรมต่อไปนี้:
ชั้นพ่อ {โมฆะสาธารณะ func1 () {func2 (); } // นี่คือวิธี func2 () ในคลาสพาเรนต์เนื่องจากวิธีการถูกแทนที่ในคลาสย่อยด้านล่าง // ดังนั้นเมื่อเรียกในการอ้างอิงของประเภทคลาสพาเรนต์วิธีนี้จะไม่ถูกต้องอีกต่อไป // แทนที่วิธี func2 () ที่ถูกแทนที่ใน subclass void func2 () }} เด็กชั้นเรียนขยายพ่อ {// func1 (int i) เป็น overload ของวิธี func1 () // เนื่องจากวิธีนี้ไม่ได้กำหนดไว้ในคลาสพาเรนต์จึงไม่สามารถเรียกได้โดยการอ้างอิงของคลาสพาเรนต์คลาส // ดังนั้นในวิธีหลักด้านล่างเด็ก func1 (68) } // func2 () เขียนวิธี func2 () ใหม่ในชั้นเรียนพ่อแม่ // ถ้าวิธี func2 () เรียกในการอ้างอิงถึงประเภทคลาสพาเรนต์มันจะต้องเป็นวิธีที่เขียนใหม่ในโมฆะสาธารณะ subclass func2 () {system.out.println ("ccc"); }} คลาสสาธารณะ polymorphismtest {โมฆะคงที่สาธารณะหลัก (String [] args) {พ่อเด็ก = เด็กใหม่ (); child.func1 (); // ผลการพิมพ์จะเป็นอย่างไร? -โปรแกรมข้างต้นเป็นตัวอย่างทั่วไปของ polymorphism เด็กชั้นเด็กสืบทอดพ่อของชั้นเรียนผู้ปกครองมากเกินไปวิธีการระดับผู้ปกครอง func1 () และเขียนทับวิธีการระดับพาเรนต์ func2 () func1 (int i) และ func1 () มากเกินไปนั้นไม่ได้เป็นวิธีเดียวกันอีกต่อไป เนื่องจากไม่มี func1 (int i) ในคลาสหลักลูกอ้างอิงของประเภทคลาสแม่จึงไม่สามารถเรียกวิธี func1 (int i) ได้ หาก subclass แทนที่วิธี func2 () ดังนั้นเด็กอ้างอิงของประเภทคลาสแม่จะเรียก func2 () ที่เขียนใหม่ในคลาสย่อยเมื่อเรียกวิธีการ
ดังนั้นโปรแกรมจะพิมพ์ผลลัพธ์อะไร?
เห็นได้ชัดว่ามันควรจะเป็น "CCC"
สำหรับ polymorphism สามารถสรุปได้ว่า:
(1) ใช้การอ้างอิงของประเภทคลาสแม่เพื่อชี้ไปที่วัตถุของคลาสย่อย (วัตถุจริง);
(2) การอ้างอิงนี้สามารถเรียกใช้วิธีการและตัวแปรที่กำหนดไว้ในคลาสแม่เท่านั้น
(3) หากวิธีการในคลาสพาเรนต์ถูกเขียนใหม่ในคลาสย่อยแล้วเมื่อเรียกใช้วิธีนี้วิธีการในคลาสย่อยจะถูกเรียก; (การเชื่อมต่อแบบไดนามิกการโทรแบบไดนามิก)
(4) ตัวแปรไม่สามารถเขียนใหม่ได้ (แทนที่) แนวคิดของ "การเขียนใหม่" มีไว้สำหรับวิธีการเท่านั้น หากตัวแปรในคลาสหลักคือ "เขียนใหม่" ในคลาสย่อยจะมีการรายงานข้อผิดพลาดระหว่างการรวบรวม
ความหลากหลายผ่าน:
(1) อินเทอร์เฟซและใช้อินเทอร์เฟซและเขียนทับคลาสที่แตกต่างกันหลายคลาสที่ครอบคลุมวิธีเดียวกันในอินเทอร์เฟซ (2) คลาสพาเรนต์และคลาสพาเรนต์และคลาสพาเรนต์และเขียนทับคลาสย่อยที่แตกต่างกันหลายรายการ
1. แนวคิดพื้นฐาน
Polymorphism: ส่งข้อความไปยังวัตถุและปล่อยให้วัตถุตัดสินใจว่าพฤติกรรมใดที่จะตอบสนอง
การเรียกใช้วิธีการแบบไดนามิกจะถูกนำมาใช้โดยการกำหนดอ้างอิงวัตถุย่อยให้กับตัวแปรอ้างอิงวัตถุ SuperClass
กลไกของ AVA นี้เป็นไปตามหลักการ: เมื่อวัตถุ superclass อ้างถึงตัวแปรเพื่ออ้างถึงวัตถุ subclass ประเภทของวัตถุอ้างอิงมากกว่าประเภทของตัวแปรอ้างอิงกำหนดวิธีการสมาชิกที่เรียกว่า แต่วิธีที่เรียกว่าต้องกำหนดไว้ใน superclass นั่นคือวิธีการที่ครอบคลุมโดย subclass
(1) หาก A เป็นการอ้างอิงถึงคลาส A ดังนั้น A สามารถชี้ไปที่อินสแตนซ์ของคลาส A หรือไปยังคลาสย่อยของคลาส A
(2) หาก A เป็นการอ้างอิงถึงอินเทอร์เฟซ A ดังนั้นต้องชี้ไปที่อินสแตนซ์ของคลาสที่ใช้อินเทอร์เฟซ A.
กลไกการใช้งาน Java Polymorphism
กลไกการใช้งาน JVM ปัจจุบันของ Sun การอ้างอิงของอินสแตนซ์คลาสคือตัวชี้ไปยังที่จับซึ่งเป็นคู่ของพอยน์เตอร์:
ตัวชี้ชี้ไปที่ตารางและในความเป็นจริงตารางนี้ยังมีสองพอยน์เตอร์ (ตัวชี้หนึ่งชี้ไปที่ตารางวิธีการที่มีวัตถุและตัวชี้อื่น ๆ ไปยังวัตถุคลาสแสดงประเภทที่วัตถุเป็นของ);
ตัวชี้อีกชิ้นชี้ไปที่พื้นที่หน่วยความจำที่จัดสรรจากกอง Java
สรุป
(1) การเรียกใช้วิธีการแบบไดนามิกจะถูกนำมาใช้โดยการกำหนดอ้างอิงวัตถุคลาสย่อยให้กับตัวแปรอ้างอิงวัตถุ SuperClass
DerivedC C2 = new derivedC (); Baseclass A1 = C2; //BaseClass base class, DerivedC is a1.play() inherited from BaseClass; //play() is defined in BaseClass and DerivedC, that is, the subclass overrides the method
วิเคราะห์:
* 为什么子类的类型的对象实例可以覆给超类引用?
自动实现向上转型。通过该语句,编译器自动将子类实例向上移动,成为通用类型BaseClass;
* a.play()将执行子类还是父类定义的方法?
子类的。在运行时期,将根据a这个对象引用实际的类型来获取对应的方法。所以才有多态性。一个基类的对象引用,被赋予不同的子类对象引用,执行该方法时,将表现出不同的行为。
在a1=c2的时候,仍然是存在两个句柄,a1和c2,但是a1和c2拥有同一块数据内存块和不同的函数表。
(2)不能把父类对象引用赋给子类对象引用变量
BaseClass a2=new BaseClass(); DerivedC c1=a2;//出错
在java里面,向上转型是自动进行的,但是向下转型却不是,需要我们自己定义强制进行。
c1=(DerivedC)a2; 进行强制转化,也就是向下转型.
(3)记住一个很简单又很复杂的规则,一个类型引用只能引用引用类型自身含有的方法和变量。
你可能说这个规则不对的,因为父类引用指向子类对象的时候,最后执行的是子类的方法的。
其实这并不矛盾,那是因为采用了后期绑定,动态运行的时候又根据型别去调用了子类的方法。而假若子类的这个方法在父类中并没有定义,则会出错。
例如,DerivedC类在继承BaseClass中定义的函数外,还增加了几个函数(例如myFun())
วิเคราะห์:
当你使用父类引用指向子类的时候,其实jvm已经使用了编译器产生的类型信息调整转换了。
这里你可以这样理解,相当于把不是父类中含有的函数从虚拟函数表中设置为不可见的。注意有可能虚拟函数表中有些函数地址由于在子类中已经被改写了,所以对象虚拟函数表中虚拟函数项目地址已经被设置为子类中完成的方法体的地址了。
(4)Java与C++多态性的比较
jvm关于多态性支持解决方法是和c++中几乎一样的,
只是c++中编译器很多是把类型信息和虚拟函数信息都放在一个虚拟函数表中,但是利用某种技术来区别。
Java把类型信息和函数信息分开放。Java中在继承以后,子类会重新设置自己的虚拟函数表,这个虚拟函数表中的项目有由两部分组成。从父类继承的虚拟函数和子类自己的虚拟函数。
虚拟函数调用是经过虚拟函数表间接调用的,所以才得以实现多态的。
Java的所有函数,除了被声明为final的,都是用后期绑定。
1个行为,不同的对象,他们具体体现出来的方式不一样,
比如: 方法重载overloading 以及方法重写(覆盖)override
class Human{ void run(){输出人在跑} } class Man extends Human{ void run(){输出男人在跑} } 这个时候,同是跑,不同的对象,不一样(这个是方法覆盖的例子) class Test{ void out(String str){输出str} void out(int i){输出i} }这个例子是方法重载,方法名相同,参数表不同
ok,明白了这些还不够,还用人在跑举例
Human ahuman=new Man();
这样我等于实例化了一个Man的对象,并声明了一个Human的引用,让它去指向Man这个对象意思是说,把Man这个对象当Human看了.
比如去动物园,你看见了一个动物,不知道它是什么, "这是什么动物? " "这是大熊猫! "
这2句话,就是最好的证明,因为不知道它是大熊猫,但知道它的父类是动物,所以,
这个大熊猫对象,你把它当成其父类动物看,这样子合情合理.
这种方式下要注意new Man();的确实例化了Man对象,所以ahuman.run()这个方法输出的是"男人在跑"
如果在子类Man下你写了一些它独有的方法比如eat(),而Human没有这个方法,
在调用eat方法时,一定要注意强制类型转换((Man)ahuman).eat(),这样才可以...
对接口来说,情况是类似的...
ตัวอย่าง:
package domain; //Define superA class superA { int i = 100; void fun(int j) { j = i; System.out.println("This is superA"); } } //Define superA subclass subB class subB extends superA { int m = 1; void fun(int aa) { System.out.println("This is subB"); } } //Define superA subC class subC extends superA { int n = 1; void fun(int cc) { System.out.println("This is subB"); } } //Define superA subC class subC extends superA { int n = 1; void fun(int cc) { System.out.println("This is subC"); } } class Test { public static void main(String[] args) { superA a = new superA(); subB b = new subB(); subC c = new subC(); a = b; a.fun(100); a = c; a.fun(200); - -
* 上述代码中subB和subC是超类superA的子类,我们在类Test中声明了3个引用变量a, b,
* c,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。也许有人会问:
* "为什么(1)和(2)不输出:This is superA"。
* java的这种机制遵循一个原则:当超类对象引用变量引用子类对象时,
* 被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,
* 但是这个被调用的方法必须是在超类中定义过的,
* 也就是说被子类覆盖的方法。
* 所以,不要被上例中(1)和(2)所迷惑,虽然写成a.fun(),但是由于(1)中的a被b赋值,
* 指向了子类subB的一个实例,因而(1)所调用的fun()实际上是子类subB的成员方法fun(),
* 它覆盖了超类superA的成员方法fun();同样(2)调用的是子类subC的成员方法fun()。
* 另外,如果子类继承的超类是一个抽象类,虽然抽象类不能通过new操作符实例化,
* 但是可以创建抽象类的对象引用指向子类对象,以实现运行时多态性。具体的实现方法同上例。
* 不过,抽象类的子类必须覆盖实现超类中的所有的抽象方法,
* 否则子类必须被abstract修饰符修饰,当然也就不能被实例化了
-
以上大多数是以子类覆盖父类的方法实现多态.下面是另一种实现多态的方法-----------重写父类方法
JAVA里没有多继承,一个类之能有一个父类。而继承的表现就是多态。一个父类可以有多个子类,而在子类里可以重写父类的方法(例如方法print()),这样每个子类里重写的代码不一样,自然表现形式就不一样。这样用父类的变量去引用不同的子类,在调用这个相同的方法print()的时候得到的结果和表现形式就不一样了,这就是多态,相同的消息(也就是调用相同的方法)会有不同的结果。举例说明:
//Premary class public class Father{ //The parent class has a method to hit the child public void hitChild(){ } } //Subclass 1 public class Son1 extends Father{ //Rewrite the method to hit the child public void hitChild(){ System.out.println("Why hit me? What I did wrong!"); } } //Subclass 2 public class Son2 extends Father{ //Rewrite the method to hit the child public void hitChild(){ System.out.println("I know I'm wrong, stop hitting it!"); } } //Subclass 3 public class Son3 extends Father{ //Rewrite the parent class hits the child method public void hitChild(){ System.out.println("I run, you can't hit!"); } } //Test class public class Test{ public static void main(String args[]){ Father father; father = new Son1(); father.hitChild(); father = new Son2(); father.hitChild(); father = new Son3(); father.hitChild(); -都调用了相同的方法,出现了不同的结果!这就是多态的表现!
import java.io.*;class Super{ Super(){ System.out.println("This is super class!"); } void method(){ System.out.println("Super's method"); }}class Sub extends Super{ Sub(){ super(); System.out.println("/n/t:and here is the child"); } void method(){ System.out.println("child's method"); }}public class Super_Sub{ public static void main(String[] args){ Super sup=new Sub(); sup.method(); Sub child=(Sub)new Super();//Here, the actual allocated memory is Super, but Child is used to refer to it. This is "downward transformation" (the parent class impersonates a child class, because the subclass is down when drawing in UML), and it must be casted by child.method(); -对于数据来说,继承是否为正确的设计可以用一个简单的规则来判断。“is-a”规则表明子类的每一个对象都是一个超类的对象。例如,每一个经理是一个员工。然而,只有经理类是员工类的子类才是有意义的。很明显,反过来就不行了――并不是每个员工都是经理。
还有一个明确叙述“is-a”规则的方法是替代原则。该原则规定无论何时,如果程序需要一个超类对象,都可以用一个子类对象来代替
动态绑定
理解调用一个对象方法的机制是非常重要的。下面具体介绍:Xf;
(1)编译器检查对象的声明类型和方法名。
(2)接着,编译器检查方法调用中的参数类型。如果在所有的叫做f的方法中有一个其参数类型同调用提供的参数类型最匹配,那么该方法就会被选择调用。这个过程称作超载选择。(静态)
(3)当程序运行并且使用动态绑定来调用一个方法时,那么虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。
-
如果类中没有写构造函数,那么系统会自动为该类提供一个默认构造函数,该构造函数将所有的实例字段初始化为默认值:
-
包用途:
Java允许把多个类收集在一起成为一组,称作包(package)。包便于组织任务,以及使自己的任务和其他人提供的代码库相分离。
标准Java库被分类成许多的包,其中包括java.1ang、java.util和java.net等等。标准Java包是分层次的。就像在硬盘上嵌套有各级子目录一样,可以通过层次嵌套组织包。所有的Java包都在Java和Javax包层次内
创建包
已经看到,已有的库,比如JavaAPI中的类和接口,可以导入到Java程序中。
Java API中的每一个类和接口属于一个特定的包。它包含一组相关联的类和接口,实际是对类和接口进行组织的目录结构。
例如,假定文件名是MyClass.java。它意味着在那个文件有一个、而且只能有一个public类。而且那个类的名字必须是MyClass(包括大小写形式):
packagemypackage;publicclass MyClass{……}创建可复用的类的步骤简要说明如下:
(1)定义一个public类。如果类不是public,它只能被同一包中的其他类使用。
(2)选择一个包名,并把package语句加到可复用的类的源代码文件中。
(3)编译这个类。这样,它就被放到适当的包目录结构中,以供编译器和解译器使用。
(4)把这个可复用的类导入到需要用它的程序中。现在就可以使用它了。
注意在Java语言中可以出现在类定义的括号外面的仅有两个语句,它们是package和import。
包引用---每个类名前加上完整的包名
例如,给出一个指向此包中的类的快捷方式。一旦使用import(导入)了以后,就不再需要给出完整的包名。
可以引入一个特定的类,也可以引入整个包。import语句要放在源文件的头部(但在所有package语句的下面)。例如,可以通过下面的语句引入在java.util包中的所有的类:
importjava.util.*;
然后,就可以使用
Datetoday=new Date();
而不需要在前面加上包名。也可以引入包中某个特定的类:
importjava.util.Date;
要把类放人一个包中,必须把此包的名字放在源文件头部,并且放在对包中的类进行定义的代码之前。例如,在文件Employee.java的开始部分如下:
packagecom.horstmann.corejava;publicclass Employee{……}把包中的文件放入与此完整的包名相匹配的子目录中。例如,在包com.horstmann.corejava中的所有的类文件都必须放在子目录com/horstmann/core.java(Windows下的com/horstmann/corejava)下。这是最简单的一种方法
类被存储在文件系统的子目录中。类的路径必须与所在包名相匹配。
在前面的例子中,包目录com/horstmann/corejava是程序目录的一个子目录。然而这样安排很不灵活。一般,有多个程序需要访问包文件。为了使包可以在多个程序间共享,需要做以下事情:
1)把类放在一个或多个特定的目录中,比如/home/user/classdir。此目录是包树的基本目录。如果加入了类com.horstmann.corejava.Employee,那么此类文件必须位于子目录/home/user/classdir/com/horstmann/corejava下。
2)设置类路径。类路径是其子目录包含类文件的所有基本目录的集合。classpath
已经接触过public和private访问指示符。
被标记为Public的部件可以被任何类使用,而私有部件只能被定义它们的类使用。如果没有指定public或private,那么部件(即类、方法或变量)可以被同一个包中的所有方法访问。
Java API包
为了简化面向对象的编程过程,Java系统事先设计并实现了一些体现了常用功能的标准类,如用于输入/输出的类,用于数学运算的类,用于图形用户界面设计的类,用于网络处理的类等。这些系统标准类根据实现的功能不同,可以划分成不同的集合,每个集合是一个包,合称为类库。可以引用这些包,也可以创建自己的包。
Java的类库是系统提供的已实现的标准类的集合,是Java编程的API,它可以帮助开发者方便、快捷地开发Java程序
接口主要作用是可以帮助实现类似于类的多重继承的功能。在Java中,出于简化程序结构的考虑,不再支持类间的多重继承而只支持单重继承,即一个类至多只能有一个直接父类。然而在解决实际问题的过程中,仅仅依靠单重继承在很多情况下都不能将问题的复杂性表述完整,需要其他的机制作为辅助。
接口声明
Java中声明接口的语法如下:
[public] interface 接口名[extends 父接口名列表]{ //接口体;//常量域声明[public] [static] [final] 域类型域名=常量值; //抽象方法声明[public] [abstract] 返回值方法名(参数列表) [throw异常列表];}从上面的语法规定可以看出,定义接口与定义类非常相似,实际上完全可以把接口理解成为一种特殊的类,接口是由常量和抽象方法组成的特殊类
(1)接口中的属性都是用final修饰的常量,
(2)接口中的方法都是用abstract修饰的抽象方法,在接口中只能给出这些抽象方法的方法名、返回值和参数列表,而不能定义方法体,即仅仅规定了一组信息交换、传输和处理的“接口”
接口的实现
一个类要实现某个或某几个接口时,有如下的步骤和注意事项:
(1)在类的声明部分,用implements关键字声明该类将要实现哪些接口;
如下:
class类名implements接口{ }(2)如果实现某接口的类不是abstract的抽象类,则在类的定义部分必须实现指定接口的所有抽象方法,即为所有抽象方法定义方法体,而且方法头部分应该与接口中的定义完全一致,即有完全相同的返回值和参数列表;
(3)如果实现某接口的类是abstract的抽象类,则它可以不实现该接口所有的方法。
(4)一个类在实现某接口的抽象方法时,必须使用完全相同的方法头。
(5)接口的抽象方法,其访问限制符都已指定是public,所以类在实现方法时,必须显式地使用public修饰符。
สรุป:
多重继承是指一个子类继承多个父类。Java不支持多重继承,但Java提供了接口。
子类不能访问父类的private成员,但子类可以访问其父类的public,protected和包访问成员;要访问父类的包访问成员,子类一定要在父类的包内。
子类构造函数总是先调用(显式的或隐式地)其父类的构造函数,以创建和初始化子类的父类成员。
子类的对象可以当作其父类的对象对待,反之则不行(即向上转型)
protected访问是public和private访问之间一个保护性的中间层次。父类方法、子类方法和在同一个包内类的方法都能访问父类的protected成员,但其他方法均不能访问
一个子类对象引用可以隐式地转换成一个父类对象引用。使用显式的类型转换,可以把父类引用转换成子类引用。如果目标不是子类对象,将产生ClassCastException例外处理。