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

การเชื่อมโยงแบบคงที่เป็นการเพิ่มประสิทธิภาพ

ในบางกรณี ประสิทธิภาพคือข้อกำหนดหลัก และแม้แต่ค่าใช้จ่ายเล็กๆ น้อยๆ ที่กล่าวมาข้างต้นก็ไม่เป็นที่พึงปรารถนา ในกรณีนี้สามารถสังเกตได้ว่าสิ่งเหล่านี้ไม่สมเหตุสมผลเสมอไป เรียก x.f (ก, ข, ค...)ไม่ต้องการการเชื่อมโยงแบบไดนามิกในกรณีต่อไปนี้:

1 ไม่ได้ถูกแทนที่ทุกที่ในระบบ (มีการประกาศเพียงรายการเดียว)

2 xไม่ใช่ polymorphic กล่าวคือ ไม่ใช่เป้าหมายของไฟล์แนบใดๆ ที่มีแหล่งที่มาเป็นประเภทอื่น

ในกรณีเหล่านี้ ตรวจพบโดยคอมไพเลอร์ที่ดี ซึ่งสร้างขึ้นเพื่อ x.f (ก, ข, ค...)รหัสอาจเหมือนกับรหัสที่สร้างโดยคอมไพเลอร์ C, Pascal, Ada หรือ Fortran ที่จะโทร ฉ (x, a, b, c...)- ไม่จำเป็นต้องมีค่าใช้จ่ายโสหุ้ย

คอมไพเลอร์ ISE ซึ่งเป็นส่วนหนึ่งของสภาพแวดล้อมที่อธิบายในการบรรยายครั้งล่าสุด กำลังดำเนินการปรับให้เหมาะสมที่สุด (1) และมีแผนจะเพิ่ม (2) (การวิเคราะห์ของ (2) อันที่จริงเป็นผลมาจากการวิเคราะห์ประเภท กลไกที่อธิบายไว้ในบรรยายเรื่องการพิมพ์)

แม้ว่า (1) จะมีความน่าสนใจในตัวเอง แต่ประโยชน์ที่ได้รับในทันทีนั้นถูกจำกัดด้วยต้นทุนที่ค่อนข้างต่ำในการเชื่อมโยงแบบไดนามิก (ดูสถิติด้านบน) ประโยชน์ที่แท้จริงจากสิ่งนี้นั้นเป็นทางอ้อม เนื่องจาก (1) อนุญาตให้มีการปรับให้เหมาะสมครั้งที่สาม:

4. ใช้ทุกครั้งที่เป็นไปได้ การทดแทนรหัสขั้นตอนโดยอัตโนมัติ.

การทดแทนดังกล่าวหมายถึงการขยายเนื้อหาของโปรแกรมด้วยข้อความของขั้นตอนที่เรียกว่า ณ ตำแหน่งที่ถูกเรียก ตัวอย่างเช่นสำหรับขั้นตอน

set_a(x:SOME_TYPE) คือ

ทำให้ x เป็นค่าใหม่ของแอตทริบิวต์ a

คอมไพเลอร์สามารถสร้างเพื่อโทรได้ s.set_a(some_value)รหัสเดียวกับที่คอมไพเลอร์ Pascal จะสร้างสำหรับการมอบหมาย s.a:= some_value(การกำหนดไม่เป็นที่ยอมรับสำหรับเราเพราะมันละเมิดการซ่อนข้อมูล) ในกรณีนี้ ไม่มีค่าใช้จ่ายใดๆ เลย เนื่องจากโค้ดที่สร้างขึ้นไม่มีการเรียกโพรซีเดอร์

การทดแทนรหัสมักถูกมองว่าเป็นการเพิ่มประสิทธิภาพที่ควรระบุ โปรแกรมเมอร์- Ada รวมถึง Pragma (คำสั่งสำหรับนักแปล) แบบอินไลน์, C และ C++ มีกลไกที่คล้ายกัน แต่แนวทางนี้มีข้อจำกัดโดยธรรมชาติ แม้ว่าสำหรับโปรแกรมขนาดเล็กแบบคงที่ โปรแกรมเมอร์ที่มีความสามารถสามารถกำหนดได้ว่าขั้นตอนใดที่สามารถนำมาใช้ทดแทนได้ แต่สำหรับโครงการที่กำลังพัฒนาขนาดใหญ่นั้นเป็นไปไม่ได้ ในกรณีนี้ คอมไพเลอร์ที่มีอัลกอริธึมที่เหมาะสมสำหรับการพิจารณาการทดแทนจะเกินกว่าที่โปรแกรมเมอร์จะคาดเดาได้มาก

สำหรับการเรียกใช้แต่ละครั้งที่ใช้การเชื่อมโยงแบบคงที่อัตโนมัติ (1) คอมไพเลอร์ OO สามารถกำหนดได้โดยอิงจากการวิเคราะห์การแลกเปลี่ยนหน่วยความจำเวลา ว่าการแทนที่โค้ดขั้นตอนอัตโนมัติ (3) นั้นคุ้มค่าหรือไม่ นี่เป็นหนึ่งในการปรับให้เหมาะสมที่น่าทึ่งที่สุด - หนึ่งในเหตุผลที่ทำให้ประสิทธิภาพของโค้ด C หรือ Fortran ที่ผลิตด้วยมือสามารถทำได้ และบางครั้งก็เหนือกว่าในระบบขนาดใหญ่

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

บันทึกสุดท้ายเกี่ยวกับประสิทธิภาพ สถิติที่เผยแพร่สำหรับภาษาเชิงวัตถุระบุว่าการโทรบางแห่งระหว่าง 30% ถึง 60% ใช้การเชื่อมโยงแบบไดนามิกจริงๆ ขึ้นอยู่กับว่านักพัฒนาใช้คุณสมบัติเฉพาะของวิธีการอย่างเข้มข้นเพียงใด ในระบบ ISE อัตราส่วนนี้ใกล้ถึง 60% ด้วยการเพิ่มประสิทธิภาพตามที่อธิบายไว้ คุณจะจ่ายเฉพาะการเชื่อมโยงแบบไดนามิกเฉพาะการโทรที่จำเป็นจริงๆ เท่านั้น สำหรับการเรียกแบบไดนามิกที่เหลือ ค่าใช้จ่ายไม่เพียงน้อย (จำกัดเฉพาะค่าคงที่) แต่ยังจำเป็นเชิงตรรกะด้วย - ในกรณีส่วนใหญ่ เพื่อให้บรรลุผลลัพธ์ที่เทียบเท่ากับการเชื่อมโยงแบบไดนามิก คุณจะต้องใช้คำสั่งแบบมีเงื่อนไข ( ถ้า... แล้ว...หรือ กรณีของ...) ซึ่งอาจมีราคาแพงกว่ากลไกแบบอาเรย์ธรรมดาข้างต้น ดังนั้นจึงไม่น่าแปลกใจที่โปรแกรม OO ที่คอมไพล์ด้วยคอมไพเลอร์ที่ดีจะสามารถแข่งขันกับโค้ด C ที่เขียนด้วยมือได้

จากหนังสือ Boost Your Website ผู้เขียน มัตซีฟสกี้ นิโคไล

การดำเนินการเก็บถาวรแบบคงที่ มีวิธีในไฟล์การกำหนดค่าเพียงไม่กี่บรรทัด (httpd.conf หรือ .htaccess ควรเป็นไฟล์แรก) หากคุณใช้เวลาสองสามนาทีและเก็บถาวรไฟล์ที่จำเป็นทั้งหมดด้วยตัวเอง สมมติว่าเรามี

จากหนังสือ The C++ Reference Guide ผู้เขียน สตรอสแตรป บีจาร์น

R.3.3 โปรแกรมและการเชื่อมโยง โปรแกรมประกอบด้วยไฟล์ตั้งแต่หนึ่งไฟล์ขึ้นไปที่เชื่อมโยงเข้าด้วยกัน (§R.2) ไฟล์ประกอบด้วยลำดับคำอธิบาย ชื่อขอบเขตไฟล์ที่ได้รับการประกาศอย่างชัดเจนแบบคงที่นั้นอยู่ในหน่วยการแปลและสามารถ

จากหนังสือภาษาการเขียนโปรแกรม C# 2005 และแพลตฟอร์ม .NET 2.0 โดย โทรลเซ่น แอนดรูว์

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

จากหนังสือ ArchiCAD 11 ผู้เขียน ดนีโปรอฟ อเล็กซานเดอร์ จี

การเชื่อมโยงมุมมอง ในบรรดาเครื่องมือแสดงภาพของ ArchiCAD มีกลไกที่มีวัตถุประสงค์เพื่อแสดงสองมุมมองที่แตกต่างกันพร้อมกัน ประเด็นคืออะไร ความต้องการสิ่งนี้เกิดขึ้นค่อนข้างบ่อย ตัวอย่างเช่น เพื่อเชื่อมโยงวัตถุด้วยภาพ

จากหนังสือความรู้พื้นฐานการเขียนโปรแกรมเชิงวัตถุ โดย เมเยอร์ เบอร์ทรานด์

Dynamic Binding การรวมกันของสองกลไกสุดท้าย การเอาชนะและความหลากหลาย สื่อถึงกลไกต่อไปนี้โดยตรง สมมติว่ามีการเรียกที่มีเป้าหมายเป็นเอนทิตีแบบ polymorphic ตัวอย่างเช่นเอนทิตีประเภท BOAT เรียกส่วนประกอบเทิร์น

จากหนังสือ System Programming in Windows Environment โดย Hart Johnson M

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

จากหนังสือ TCP/IP Architecture, Protocols, Implementation (รวมถึง IP เวอร์ชัน 6 และ IP Security) โดย Faith Sydney M

การผูกแบบไดนามิก การผูกแบบไดนามิกจะช่วยเสริมการแทนที่ ความหลากหลาย และการพิมพ์แบบคงที่ ทำให้เกิด tetralogy พื้นฐาน

จากหนังสือ VBA สำหรับ Dummies โดย สตีฟ คัมมิงส์

ปุ่มโดยใช้ชื่ออื่น: เมื่อการเชื่อมโยงแบบคงที่ไม่ถูกต้อง ในตอนนี้ ประเด็นสำคัญจากหลักการของการสืบทอดที่ระบุไว้ในการบรรยายนี้ควรจะชัดเจน: หลักการของการเชื่อมโยงแบบไดนามิก เมื่อผลลัพธ์ของการเชื่อมโยงแบบคงที่ไม่ตรงกับผลลัพธ์

จากหนังสือระบบปฏิบัติการ UNIX ผู้เขียน โรบาเชฟสกี้ อังเดร เอ็ม.

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

จากหนังสือ C++ สำหรับผู้เริ่มต้น โดย ลิปป์แมน สแตนลีย์

การเชื่อมโยงโดยนัย การเชื่อมโยงโดยนัยหรือการเชื่อมโยงเวลาโหลดเป็นวิธีที่ง่ายกว่าในเทคนิคการเชื่อมโยงทั้งสองแบบ ขั้นตอนการใช้งาน Microsoft C++ มีดังนี้ 1. หลังจากรวบรวมฟังก์ชันทั้งหมดที่จำเป็นสำหรับ DLL ใหม่แล้ว

จากหนังสือการพัฒนาเคอร์เนล Linux โดย รักโรเบิร์ต

การเชื่อมโยงที่ชัดเจน การเชื่อมโยงอย่างชัดเจนหรือการเชื่อมโยงรันไทม์ ต้องการให้โปรแกรมให้คำแนะนำเฉพาะเกี่ยวกับเวลาที่จะโหลดหรือปล่อย DLL ต่อไปโปรแกรมจะได้รับที่อยู่ตามที่ร้องขอ

จากหนังสือของผู้เขียน

11.9.3 การเชื่อม เซิร์ฟเวอร์ DHCP จะรักษาตารางการแมประหว่างไคลเอนต์และพารามิเตอร์การกำหนดค่า การเชื่อมโยงประกอบด้วยการกำหนดที่อยู่ IP และชุดการกำหนดค่าให้กับลูกค้าแต่ละราย

จากหนังสือของผู้เขียน

สถานะแบบคงที่ คำสำคัญแบบคงที่ในการประกาศตัวแปรควรใช้เมื่อคุณต้องการให้ตัวแปรยังคงอยู่ในหน่วยความจำ - เพื่อให้สามารถใช้ค่าได้ - แม้ว่าขั้นตอนจะเสร็จสิ้นการทำงานแล้วก็ตาม ในตัวอย่างต่อไปนี้ ตัวแปร

จากหนังสือของผู้เขียน

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

จากหนังสือของผู้เขียน

9.1.7. Safe Binding A เมื่อใช้งานโอเวอร์โหลด ดูเหมือนว่าโปรแกรมจะมีฟังก์ชันหลายฟังก์ชันในชื่อเดียวกันพร้อมรายการพารามิเตอร์ที่แตกต่างกัน อย่างไรก็ตาม ความสะดวกสบายของคำศัพท์นี้มีเฉพาะในระดับข้อความต้นฉบับเท่านั้น ในส่วนใหญ่

จากหนังสือของผู้เขียน

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

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

ใน Java ตัวแปรวัตถุเป็นแบบ polymorphic ตัวอย่างเช่น:
class King ( โมฆะสาธารณะคงที่ main (String args) ( King king = new King() ; king = new AerysTargaryen() ; king = new RobertBaratheon() ; ) ) คลาส RobertBaratheon ขยาย King ( ) คลาส AerysTargaryen ขยาย King ( )
ตัวแปรประเภท King สามารถอ้างอิงถึงวัตถุประเภท King หรือวัตถุของคลาสย่อยของ King ก็ได้
ลองใช้ตัวอย่างต่อไปนี้:

class King ( public void Speech() ( System .out .println ("I"m the King of the Andals!" ) ; ) public void Speech(สตริงคำพูด) ( System .out .println ("Wise man says: " + ใบเสนอราคา); ) คำพูดที่เป็นโมฆะสาธารณะ (บูลีนพูดเสียงดัง) ( ถ้า (พูดเสียงดัง) ระบบ .out .println ( "ฉันคือราชาแห่งอันดาลส์!!!11"-
else System .out .println ("i"m... the king..." ) ; ) ) คลาส AerysTargaryen ขยาย King ( @Override public void Speech() ( System .out .println ("Burn they all... " ) ; ) @Override คำพูดเป็นโมฆะสาธารณะ(ใบเสนอราคาสตริง) ( System .out .println (quotation+ " ... และตอนนี้เผามันทั้งหมด!" ) ; ) ) class Kingdom ( public static void main(String args) ( King king = ใหม่ AerysTargaryen() ; king.speech ("Homo homini lupus est" ) )จะเกิดอะไรขึ้นเมื่อมีการเรียกใช้เมธอดที่เป็นของออบเจ็กต์

กษัตริย์?1. คอมไพเลอร์จะตรวจสอบประเภทอ็อบเจ็กต์ที่ประกาศและชื่อเมธอด โดยระบุชื่อเมธอดทั้งหมดด้วยชื่อคำพูด ในคลาส AerusTargarienและวิธีการสาธารณะทั้งหมด
คำพูดในซูเปอร์คลาสเอรัส ทาร์แกเรียน
- คอมไพเลอร์ตอนนี้รู้ตัวเลือกที่เป็นไปได้เมื่อเรียกใช้เมธอด2. คอมไพลเลอร์จะกำหนดประเภทของอาร์กิวเมนต์ที่ส่งผ่านไปยังเมธอด หากพบวิธีการเดียวที่มีลายเซ็นตรงกับอาร์กิวเมนต์ การโทรจะเกิดขึ้นกระบวนการนี้ king.speech("ตุ๊ด homini lupus est")คอมไพเลอร์จะเลือกวิธีการคำพูด (คำพูดสตริง) , แต่ไม่.

คำพูด()หากคอมไพเลอร์พบหลายวิธี



ด้วยพารามิเตอร์ที่เหมาะสม (หรือไม่มีเลย) ข้อความแสดงข้อผิดพลาดจะปรากฏขึ้น
คอมไพเลอร์รู้ชื่อและประเภทของพารามิเตอร์ของวิธีการที่จะเรียกแล้ว3.ในกรณีที่วิธีที่เรียกคือ, ส่วนตัว, คงที่สุดท้าย หรือตัวสร้างจะใช้การเชื่อมโยงแบบคงที่ (มีผลผูกพันตั้งแต่เนิ่นๆ - ในกรณีอื่นๆ วิธีการที่จะเรียกจะถูกกำหนดโดยชนิดที่แท้จริงของออบเจ็กต์ที่เกิดการโทร เหล่านั้น. ใช้ระหว่างการทำงานของโปรแกรม.

การเชื่อมโยงแบบไดนามิก (การเชื่อมโยงล่าช้า)
4. เครื่องเสมือนจะสร้างตารางวิธีการไว้ล่วงหน้าสำหรับแต่ละคลาสที่แสดงรายการลายเซ็นของวิธีการทั้งหมดและวิธีการจริงที่จะเรียกใช้ตารางวิธีการเรียนกษัตริย์
  • ดูเหมือนว่า: คำพูด() -, แต่ไม่
  • กษัตริย์.คำพูด() -คำพูด (คำพูดแบบสตริง) -
  • คำพูด() -คำพูด (คำพูดสตริง)
คำพูด (บูลีนพูดเสียงดัง)และสำหรับชั้นเรียนนั้น
  • AerysTargaryen - แบบนี้:คำพูด() - . , แต่ไม่
  • กษัตริย์.แอรีส ทาร์แกเรียน
  • แอรีส ทาร์แกเรียน. คำพูด (คำพูดสตริง)คำพูด(บูลีนพูดเสียงดัง) -กษัตริย์
- คำพูด (บูลีนพูดเสียงดัง)
วิธีการที่สืบทอดมาจาก Object จะถูกละเว้นในตัวอย่างนี้เมื่อโทรกษัตริย์.
  1. คำพูด() :มีการกำหนดประเภทที่แท้จริงของตัวแปร กษัตริย์- ในกรณีนี้ก็คือ.
  2. แอรีส ทาร์แกเรียน, แต่ไม่
  3. เครื่องเสมือนกำหนดคลาสที่เป็นของวิธีการ
วิธีการนี้เรียกว่าเชื่อมโยงทุกวิถีทางเข้าด้วยกันชวาการเชื่อมโยงแบบไดนามิกมีคุณลักษณะที่สำคัญประการหนึ่ง: อนุญาตแก้ไขโปรแกรมโดยไม่ต้องคอมไพล์รหัสใหม่ นี่คือสิ่งที่โปรแกรมทำขยายได้แบบไดนามิก ( ขยายได้).
จะเกิดอะไรขึ้นหากคุณเรียกใช้เมธอดที่ถูกผูกไว้แบบไดนามิกของวัตถุที่สร้างขึ้นในตัวสร้าง? ตัวอย่างเช่น:
คลาสคิง ( คิง () ( System . out . println ( "เรียกตัวสร้างคิง" ) ; คำพูด () ; //แทนที่วิธี polymorphic ใน AerysTargaryen) public void Speech() ( System .out .println ("I"m the King of the Andals!" ) ; ) ) คลาส AerysTargaryen ขยาย King ( private String allowanceName; AerysTargaryen() ( System .out .println ( "โทรหาผู้สร้าง Aerys Targaryen"- ชื่อเหยื่อ = "ลีอันนา สตาร์ค" ; คำพูด() ;

) @Override public void Speech() ( System .out .println ("Burn " + allowanceName + "!" ) ; ) ) class Kingdom ( public static void main(String args) ( King king = new AerysTargaryen() ; ) ) ผลลัพธ์: โทรหาผู้สร้างคิง!
เบิร์นโมฆะ!
โทรหาผู้สร้าง Aerys Targaryen เบิร์น ลีอันนา สตาร์คตัวสร้างของคลาสพื้นฐานจะถูกเรียกเสมอระหว่างการสร้างคลาสที่ได้รับ การเรียกจะเลื่อนสายการสืบทอดขึ้นโดยอัตโนมัติ ดังนั้นในที่สุดตัวสร้างของคลาสพื้นฐานทั้งหมดตลอดสายการสืบทอดจะถูกเรียกในที่สุด
  1. ซึ่งหมายความว่าเมื่อเรียกตัวสร้าง
  2. ใหม่ AerysTargaryen() จะถูกเรียกว่า:
  3. ใหม่วัตถุ()คิงองค์ใหม่()
ใหม่

แอรีสทาร์แกเรียน()

ตามคำนิยาม งานของนักออกแบบคือการทำให้วัตถุมีชีวิต ภายในตัวสร้างใดๆ วัตถุสามารถสร้างขึ้นได้เพียงบางส่วนเท่านั้น ทั้งหมดที่ทราบก็คือวัตถุคลาสพื้นฐานได้รับการเตรียมใช้งานแล้ว หาก Constructor เป็นเพียงอีกก้าวหนึ่งในการสร้างคลาสอ็อบเจ็กต์ที่ได้มาจากคลาสของ Constructor นี้ ส่วนที่ "ได้มา" ยังไม่ได้รับการเริ่มต้น ณ เวลาที่ Constructor ปัจจุบันถูกเรียก

  1. อย่างไรก็ตาม การเรียกที่ถูกผูกไว้แบบไดนามิกสามารถไปที่ส่วน "ภายนอก" ของลำดับชั้น ซึ่งก็คือ ไปยังคลาสที่ได้รับ หากเขาเรียกเมธอดคลาสที่ได้รับในตัวสร้าง สิ่งนี้สามารถนำไปสู่การยักย้ายข้อมูลที่ไม่ได้เตรียมใช้งาน ซึ่งเป็นสิ่งที่เราเห็นในผลลัพธ์ของตัวอย่างนี้
  2. ผลลัพธ์ของโปรแกรมถูกกำหนดโดยการดำเนินการของอัลกอริธึมการเริ่มต้นวัตถุ:หน่วยความจำที่จัดสรรสำหรับวัตถุใหม่เต็มไปด้วยเลขศูนย์ไบนารี ตัวสร้างคลาสฐานถูกเรียกตามลำดับที่อธิบายไว้ก่อนหน้านี้ ณ จุดนี้จะมีการเรียกเมธอดที่ถูกแทนที่- ในกรณีนี้ก็คือคำพูด()ชื่อเหยื่อเป็นโมฆะ เพราะระยะแรก
  3. ตัวเริ่มต้นสมาชิกคลาสจะถูกเรียกตามลำดับที่ถูกกำหนดไว้
  4. เนื้อความของตัวสร้างคลาสที่ได้รับถูกดำเนินการ
โดยเฉพาะอย่างยิ่งเนื่องจากปัญหาด้านพฤติกรรมดังกล่าว จึงควรปฏิบัติตามกฎต่อไปนี้ในการเขียนตัวสร้าง:
- ดำเนินการในตัวสร้างเฉพาะการกระทำที่จำเป็นและง่ายที่สุดเพื่อเริ่มต้นวัตถุ
- หากเป็นไปได้ ให้หลีกเลี่ยงการเรียกวิธีการที่ไม่ได้กำหนดไว้ส่วนตัวหรือขั้นสุดท้าย (ซึ่งในบริบทนี้ก็เป็นสิ่งเดียวกัน)
วัสดุที่ใช้:
  1. เอคเคล บี.-คิดในชวา , ฉบับพิมพ์ครั้งที่ 4 - บทที่ 8
  2. เคย์ เอส. ฮอร์สต์แมนน์, แกรี่ คอร์เนล -คอร์ Java 1 - บทที่ 5
  3. วิกิพีเดีย

เริ่มตั้งแต่ PHP 5.3.0 มีคุณลักษณะที่เรียกว่า late staticbinding ซึ่งสามารถใช้เพื่อรับการอ้างอิงถึงคลาสที่สามารถเรียกได้ในบริบทของการสืบทอดแบบคงที่

แม่นยำยิ่งขึ้น การเชื่อมโยงแบบคงที่ล่าช้าจะรักษาชื่อของคลาสที่ระบุใน "การโทรที่ไม่ส่งต่อ" ครั้งล่าสุด ในกรณีของการโทรแบบคงที่ นี่คือคลาสที่ระบุอย่างชัดเจน (โดยปกติจะอยู่ทางด้านซ้ายของตัวดำเนินการ :: - ในกรณีของการเรียกแบบไม่คงที่ นี่คือคลาสของอ็อบเจ็กต์ "การโทรเปลี่ยนเส้นทาง" คือการโทรแบบคงที่ที่เริ่มต้นด้วย, ตัวเอง::, พ่อแม่::คงที่:: หรือถ้าเราเลื่อนลำดับชั้นของคลาสขึ้นส่งต่อ_static_call() -การทำงาน พ่อแม่:: get_call_class()

สามารถใช้เพื่อรับสตริงที่มีชื่อของคลาสที่เรียกว่าและ พ่อแม่::แสดงถึงขอบเขตของมัน

ชื่อ “การเชื่อมโยงแบบคงที่ล่าช้า” นั้นสะท้อนถึงการใช้งานคุณลักษณะนี้ภายใน "การผูกมัดล่าช้า" สะท้อนถึงข้อเท็จจริงที่ผ่านไป ในกรณีของการเรียกแบบไม่คงที่ นี่คือคลาสของอ็อบเจ็กต์ "การโทรเปลี่ยนเส้นทาง" คือการโทรแบบคงที่ที่เริ่มต้นด้วย

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

ข้อ จำกัด
ตัวอย่าง #1 การใช้งาน ;
}
คลาสเอ (
ก้อง __คลาส__
ฟังก์ชั่นคงที่สาธารณะ
}
}

ทดสอบ()(
ตัวเอง::ใคร();
คลาส B ขยาย A (
}
}

ฟังก์ชันคงที่สาธารณะ who() (
?>

เสียงสะท้อน __คลาส__ ;

B::ทดสอบ(); การใช้การผูกแบบคงที่ตอนปลายการเชื่อมโยงแบบคงที่ในภายหลังพยายามเอาชนะข้อจำกัดนี้โดยจัดเตรียมคีย์เวิร์ดที่อ้างอิงถึงคลาสที่เรียกโดยตรงที่รันไทม์ พูดง่ายๆ ก็คือ คำหลักที่จะช่วยให้คุณสามารถเชื่อมโยงไปถึงได้ บีจาก ทดสอบ()ในตัวอย่างก่อนหน้านี้ มีการตัดสินใจว่าจะไม่แนะนำคำหลักใหม่ แต่ให้ใช้

ตัวอย่างที่ 2 ใช้งานง่าย พ่อแม่::

ข้อ จำกัด
ตัวเอง::ใคร();
ตัวอย่าง #1 การใช้งาน ;
}
คลาสเอ (
ก้อง __คลาส__
คงที่::ใคร(); // มีผลผูกพันแบบคงที่ล่าช้าที่นี่
}
}

ทดสอบ()(
ตัวเอง::ใคร();
คลาส B ขยาย A (
}
}

ฟังก์ชันคงที่สาธารณะ who() (
?>

ผลลัพธ์ของการรันตัวอย่างนี้:

ความคิดเห็น:

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

ตัวอย่าง #3 การใช้งาน พ่อแม่::ในบริบทที่ไม่คงที่

ข้อ จำกัด
ฟังก์ชั่นส่วนตัว foo() (
สะท้อน "ความสำเร็จ!\n" ;
}
การทดสอบฟังก์ชั่นสาธารณะ () (
$นี่ -> ฟู();
คงที่::foo();
}
}

ทดสอบ()(
/* foo() จะถูกคัดลอกไปที่ B ดังนั้นขอบเขตของมันจึงยังคงเป็น A
และการโทรจะสำเร็จ*/
}

คลาส C ขยาย A (
ฟังก์ชั่นส่วนตัว foo() (
/* วิธีการเดิมถูกแทนที่; ขอบเขตของวิธี C ใหม่ */
}
}

$b = B ใหม่();
$b -> ทดสอบ();
$c = C ใหม่();
$c -> ทดสอบ(); //ไม่จริง
?>

ผลลัพธ์ของการรันตัวอย่างนี้:

ความสำเร็จ! ความสำเร็จ! ความสำเร็จ! ข้อผิดพลาดร้ายแรง: การเรียกไปยังวิธีส่วนตัว C::foo() จากบริบท "A" ใน /tmp/test.php ออนไลน์ 9

ความคิดเห็น:

ขอบเขตการแก้ไขของการผูกแบบคงที่ล่าช้าจะได้รับการแก้ไขโดยการเรียกแบบคงที่ที่คำนวณ ในทางกลับกัน การโทรแบบคงที่โดยใช้คำสั่งเช่น ตัวเอง::หรือ ในกรณีของการเรียกแบบไม่คงที่ นี่คือคลาสของอ็อบเจ็กต์ "การโทรเปลี่ยนเส้นทาง" คือการโทรแบบคงที่ที่เริ่มต้นด้วยเปลี่ยนเส้นทางข้อมูลการโทร

ตัวอย่างที่ 4 การโทรที่เปลี่ยนเส้นทางและไม่เปลี่ยนเส้นทาง

ผูกพัน- การทดแทนการเรียกใช้ฟังก์ชันเฉพาะเป็นรหัสโปรแกรม - วิธีการเรียน- เหมาะสมสำหรับคลาสที่ได้รับเท่านั้น

โดยปกติแล้วคอมไพลเลอร์จะมีข้อมูลที่จำเป็นในการพิจารณาว่าฟังก์ชันใดหมายถึงอะไร ตัวอย่างเช่น หากโปรแกรมพบการเรียก obj.f() คอมไพเลอร์จะเลือกฟังก์ชัน f() โดยไม่ซ้ำกัน ขึ้นอยู่กับประเภทของ obj ปลายทาง หากโปรแกรมใช้พอยน์เตอร์กับอินสแตนซ์ของ class:ptr->f() การเลือกฟังก์ชัน - วิธีการคลาสจะถูกกำหนดโดยประเภทของพอยน์เตอร์

หากการเลือกฟังก์ชั่นเสร็จสิ้นในเวลารวบรวม เรากำลังเผชิญกับ การเชื่อมโยงแบบคงที่.

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

หากทำการเลือกฟังก์ชั่นในขั้นตอนการทำงานของโปรแกรม เรากำลังเผชิญอยู่ การเชื่อมโยงแบบไดนามิก.

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

ฟังก์ชั่นเสมือน

ตามค่าเริ่มต้น คลาสที่ได้รับจะมีการเชื่อมโยงแบบคงที่ ถ้าจะใช้การเชื่อมโยงแบบไดนามิกสำหรับวิธีการเรียนใด ๆ วิธีการดังกล่าวจะต้องได้รับการประกาศ เสมือน .

ฟังก์ชั่นเสมือน:

    มีคีย์เวิร์ดเสมือนในต้นแบบในคลาสพื้นฐาน

    ฟังก์ชั่นสมาชิกคลาสบังคับ:

    คลาสที่ได้รับมาทั้งหมดจะต้องมีต้นแบบเดียวกัน (ไม่จำเป็นต้องระบุคำว่า virtual ในคลาสที่ได้รับมา)

หากวิธีการใดๆ ในคลาสที่ได้รับมีชื่อเหมือนกับในคลาสพื้นฐาน แต่มีรายการพารามิเตอร์ที่แตกต่างกัน แสดงว่ามีฟังก์ชันโอเวอร์โหลด

ตัวอย่าง: ชั้นเรียนจุดและวงกลม

การพิมพ์โมฆะเสมือน ();

คลาสวงกลม: จุดสาธารณะ (

พิมพ์เป็นโมฆะ(); // คุณสามารถพิมพ์โมฆะเสมือน ();

จุดโมฆะ::พิมพ์()

ศาล<< "Point (" << x << ", " << y << ")";

เป็นโมฆะวงกลม::พิมพ์()

ศาล<< "Circle with center in "; Point::print();

ศาล<< "and radius " << rad;

การใช้งาน:

จุด p1(3,5), p2(1,1), *pPtr;

วงกลม c1(1), c2(p2, 1);

pPtr = pPtr->พิมพ์(); // รับ: จุด (3, 5)

pPtr = pPtr->พิมพ์(); // รับ:

วงกลมโดยมีศูนย์กลางอยู่ที่จุด (1, 1) และรัศมี 1

ตัวอย่างการผูกแบบไดนามิก: รายการ

การใช้การเชื่อมโยงแบบไดนามิกที่พบบ่อยที่สุดคือกับคลาสคอนเทนเนอร์ที่มีตัวชี้ไปยังคลาสฐาน คลาสคอนเทนเนอร์ดังกล่าวสามารถรวมข้อมูลที่เกี่ยวข้องกับทั้งคลาสพื้นฐานและคลาสที่ได้รับใดๆ

ลองพิจารณาตัวอย่าง - รายการที่มีทั้งจุดและวงกลม

// ตัวสร้าง

รายการ():ข้อมูล(NULL) ถัดไป(NULL)()

รายการ (จุด *p):ข้อมูล(p), ถัดไป(NULL)()

รายการ():หัว(โมฆะ)()

การแทรกเป็นโมฆะ (จุด *p)(p->ถัดไป = head; head = p;)

รายการโมฆะ::พิมพ์()

สำหรับ(รายการ *cur = head; cur; cur = cur->ถัดไป)(

cur -> ข้อมูล -> พิมพ์ ();

ศาล<< endl;

การใช้คลาส:

จุด *p = จุดใหม่ (1,2);

mylist.insert(พี);

p = วงจรใหม่ (1,2,1);

mylist.insert(พี);

วงกลมโดยมีศูนย์กลางอยู่ที่จุด (1, 2) และรัศมี 1

มีระบบจำนวนมากและเพิ่มขึ้นเรื่อยๆ ซึ่งการสื่อสารแบบคงที่ในระดับที่รุนแรงสามารถส่งผลเชิงบวกอย่างมากต่อแอปพลิเคชันและประสิทธิภาพของระบบ

ฉันกำลังพูดถึงสิ่งที่มักเรียกว่า "ระบบฝังตัว" ซึ่งหลายระบบใช้ระบบปฏิบัติการทั่วไปมากขึ้นเรื่อยๆ และระบบเหล่านี้ก็ใช้สำหรับทุกสิ่งเท่าที่จะจินตนาการได้

ตัวอย่างที่พบบ่อยมากคืออุปกรณ์ที่ใช้ระบบ GNU/Linux ที่ใช้ Busybox ฉันทำสิ่งนี้อย่างสุดขีดด้วย NetBSD ด้วยการสร้างอิมเมจระบบ i386 (32 บิต) ที่สามารถบูตได้ซึ่งมีทั้งเคอร์เนลและระบบไฟล์รูทซึ่งมีไบนารีที่เชื่อมโยงแบบคงที่ (ผ่าน crunchgen) หนึ่งตัวพร้อมฮาร์ดลิงก์ไปยังโปรแกรมทั้งหมด ซึ่ง บรรจุ ทั้งหมด(สุดท้ายก็นับ 274) (ส่วนใหญ่ไม่รวม toolchain) และนั่นน้อยกว่า 20 เมกะไบต์ (และอาจทำงานได้อย่างสะดวกสบายมากบนระบบที่มีหน่วยความจำ 64MB (แม้ว่าระบบไฟล์รูทจะไม่ถูกบีบอัดและอยู่ใน RAM ทั้งหมด) แม้ว่าฉันจะไม่พบอันที่เล็กขนาดนั้นที่จะทดสอบก็ตาม

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

อย่างไรก็ตาม นี่ไม่ใช่เรื่องราวทั้งหมด โดยทั่วไปแล้ว ฉันยังสร้างและใช้การติดตั้งระบบปฏิบัติการ NetBSD สำหรับระบบการพัฒนาที่สมบูรณ์ของฉันโดยการเชื่อมโยงไบนารีทั้งหมดแบบคงที่ แม้ว่าการดำเนินการนี้ต้องการพื้นที่ดิสก์จำนวนมาก (รวมประมาณ 6.6GB สำหรับ x86_64 พร้อมด้วยทุกอย่างรวมถึง toolchain และ X11 static-linked) (โดยเฉพาะอย่างยิ่งหากคุณเก็บตารางสัญลักษณ์การแก้ไขข้อบกพร่องแบบเต็มไว้สำหรับโปรแกรมทั้งหมดในราคา ~2 เพิ่มเติม .5 GB) ผลลัพธ์โดยรวมยังเร็วกว่า และบางงานยังใช้หน่วยความจำน้อยกว่าระบบเชื่อมโยงแบบไดนามิกทั่วไปที่ออกแบบมาเพื่อแลกเปลี่ยนโค้ดเพจไลบรารี ดิสก์มีราคาถูก (แม้แต่ดิสก์แบบเร็ว) และหน่วยความจำสำหรับการแคชไฟล์ที่ใช้บ่อยบนดิสก์ก็มีราคาค่อนข้างถูกเช่นกัน แต่วงจรของ CPU นั้นราคาถูกจริงๆ และการจ่ายรายได้เริ่มต้นของ ld.so สำหรับแต่ละกระบวนการที่เริ่มต้นทุกครั้งที่เริ่มทำงานจะใช้เวลาหลายชั่วโมง และจำนวนชั่วโมงของวงจร CPU จากงานที่ต้องใช้กระบวนการจำนวนมากในการรัน โดยเฉพาะอย่างยิ่งเมื่อมีการใช้โปรแกรมเดียวกันซ้ำแล้วซ้ำอีก เช่น คอมไพเลอร์บนระบบการพัฒนา โปรแกรมซอฟต์แวร์แบบบันเดิลแบบคงที่สามารถลดเวลาที่ต้องใช้ในการสร้างสถาปัตยกรรมมัลติคาสต์สำหรับทั้งระบบได้ภายในไม่กี่ชั่วโมง ฉันยังไม่ได้สร้าง toolchain ในไบนารี่ crunchgen" เดี่ยวของฉัน แต่ฉันสงสัยว่าเมื่อฉันสร้าง จะได้ประหยัดเวลาในการสร้างมากขึ้นเนื่องจากแคช CPU เพิ่มขึ้น