Computer >> คอมพิวเตอร์ >  >> สมาร์ทโฟน >> iPhone

เรื่องราวของแม่หนึ่งคนและลูกชายสองคน:ประเภทค่าเทียบกับประเภทอ้างอิงใน Swift

สวิฟท์เป็นแม่?และมีลูกชายสองคน ?-

  • ประเภทค่า ??‍♀️
  • ประเภทอ้างอิง ?‍♂️

แต่ลักษณะของพวกเขาคืออะไร??‍♂️

พวกเขาประพฤติเหมือนหรือตรงกันข้ามกันหรือไม่? ?‍♂️

Swift เป็นภาษาการเขียนโปรแกรมแบบหลายกระบวนทัศน์ที่พัฒนาโดย Apple สำหรับ iOS, macOS, watchOS, tvOS, Linux และ z/OS?

เช่นเดียวกับภาษาการเขียนโปรแกรมเชิงวัตถุอื่น ๆ Swift มีคลาสเป็นหน่วยการสร้างซึ่งสามารถกำหนดวิธีการ คุณสมบัติ ตัวเริ่มต้น และสามารถสอดคล้องกับโปรโตคอล รองรับการสืบทอดและความหลากหลาย?

แต่เดี๋ยวก่อน รอ…???

Swift มี struct ด้วย และสามารถกำหนดเมธอด คุณสมบัติ ตัวเริ่มต้น และสามารถสอดคล้องกับโปรโตคอลได้โดยมีข้อยกเว้นเพียงข้อเดียวในการสืบทอด?

อะไร ตอนนี้สับสน!!! ???

ตอนนี้ มาเพิ่มความสับสนของคุณ:โครงสร้างไม่ได้เป็นเพียงประเภทค่าใน Swift Tuples และ enums เป็นประเภทค่าเช่นกัน คลาสไม่ใช่คลาสเดียวที่ใช้เป็นประเภทอ้างอิง ฟังก์ชันและการปิดเป็นประเภทอ้างอิงเช่นกัน แต่เพื่อเป็นสัญลักษณ์แห่งความโล่งใจ อย่างน้อยเราก็รู้จุดเน้นหลักและความเชี่ยวชาญเฉพาะด้านของการใช้งานประเภทนี้

จนถึงตอนนี้ เราเหลือเพียงความสับสนครั้งใหญ่เพียงครั้งเดียวกับการใช้โครงสร้างและคลาส?

ไปกันเถอะ ไปเคลียร์ความสับสนที่เกิดขึ้น?‍♂️

ตำแหน่งที่จัดเก็บ

มีที่เก็บข้อมูลสามประเภท:

  • ลงทะเบียน ?
  • กอง ☄️
  • กอง ?

ออบเจ็กต์ที่มีอายุการใช้งานสั้นลงจะถูกเก็บไว้ในรีจิสเตอร์หรือสแต็ก และอ็อบเจ็กต์ที่มีอายุการใช้งานยาวนานกว่าจะถูกเก็บไว้ในฮีป

ประเภทค่าจะจัดเก็บเนื้อหาในหน่วยความจำที่จัดสรรในสแต็ก ดังนั้นเราสามารถพูดได้ว่าประเภทค่าได้รับการจัดสรรในสแต็กใน Swift ?

แต่มีความเข้าใจผิดทั่วไปเกี่ยวกับประเภทค่านิยม คุณเคยได้ยินไหม??‍♂️

ความเข้าใจผิดคือคนส่วนใหญ่คิดว่าประเภทค่าจะถูกเก็บไว้ในสแต็กเสมอ

❌❌รอสักครู่ — ไม่ใช่กรณีนี้เสมอไป ❌❌

ประเภทค่าสามารถเก็บไว้ในสแต็กได้เมื่อเป็นตัวแปรชั่วคราวหรือตัวแปรในเครื่อง แต่ถ้าประเภทค่าอยู่ในประเภทอ้างอิงล่ะ

ในสถานการณ์นี้ สามารถเก็บไว้ในหน่วยความจำฮีปได้ ?

ว้าว…เจ๋งไปเลย!!!?

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

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

มันทำงานอย่างไรสำหรับประเภทอ้างอิง ??

ดังนั้นสำหรับประเภทการอ้างอิง จึงเป็นเรื่องปกติที่จะมีตัวแปรหลายตัวที่อ้างอิงไปยังตำแหน่งหน่วยความจำเดียวกัน⚔️

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

ความแตกต่างในแง่ของความไม่แน่นอน

ตัวแปรสามารถมีได้สองสถานะ:

  • ?‍♀ ️เปลี่ยนได้ ?‍♀
  • ?️‍♂️ ไม่เปลี่ยนรูป ?️‍♂️

หากอินสแตนซ์ประเภทค่าถูกกำหนดให้กับตัวแปรที่ไม่เปลี่ยนรูป อินสแตนซ์นั้นก็จะเปลี่ยนไม่ได้เช่นกัน เป็นผลให้เราไม่สามารถทำการเปลี่ยนแปลงใด ๆ กับอินสแตนซ์นั้นได้?‍♂️

หากอินสแตนซ์ประเภทค่าถูกกำหนดให้กับตัวแปรที่เปลี่ยนแปลงได้ อินสแตนซ์นั้นจะทำให้อินสแตนซ์นั้นเปลี่ยนได้เท่านั้น ?‍♂️

แต่สิ่งต่าง ๆ โดยสิ้นเชิงสำหรับประเภทการอ้างอิง ตัวแปรและอินสแตนซ์ที่ได้รับมอบหมายนั้นแตกต่างกันโดยสิ้นเชิง หากเราประกาศตัวแปรที่ไม่เปลี่ยนรูปซึ่งมีการอ้างอิงถึงคลาส หมายความว่าการอ้างอิงที่เก็บไว้จะไม่เปลี่ยนแปลง เราไม่สามารถเปลี่ยนการอ้างอิงได้ และจะชี้ไปที่การอ้างอิงเดียวกันเสมอ ?

ประเภทโครงสร้าง

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

อืม...คำแรงเกินไป...หมายความว่าไง???

สมมติว่าเรามี บุคคล ประเภทค่าที่มีแอตทริบิวต์เช่น firstName และ นามสกุล

struct Person {
   var firstName: String
   var lastName: String
}

var person1 = Person(firstName: "foo", lastName: "bar")

var person2 = Person(firstName: "foo", lastName: "bar")

ที่นี่ทั้ง person1 &บุคคล2 อินสแตนซ์มีค่าเดียวกันสำหรับ firstName (“foo”) และ นามสกุล (“บาร์”) . ตามความเข้าใจของเรา เราสามารถพูดได้ว่าอินสแตนซ์ทั้งสองมีค่าเท่ากันเนื่องจากแอตทริบิวต์ (firstName &นามสกุล ) มีค่าเท่ากัน

แต่ไม่ได้จำกัดอยู่แค่เพียงกรณีนี้เท่านั้น:ในอนาคต จะมีบุคคลสองคนที่มีค่าเท่ากับ firstName &นามสกุล จะเท่าเทียมกัน

ตามความเข้าใจของเราจนถึงจุดนี้ เราสามารถพูดได้ว่า:

ประเภทค่าไม่มีข้อมูลประจำตัว ดังนั้นจึงไม่มีการอ้างอิงถึงค่าเหล่านี้ ประเภทค่าไม่มีตัวตน

อะไร พูดได้ยังไงเนี่ย????

var myAge: Int = 21
var friendAge: Int = 21

ทั้ง myAge &friendAge เป็นตัวแปรประเภทจำนวนเต็มที่มีค่า 21

เราแยกความแตกต่างออกจากกันได้ไหม? ?

ไม่ เพราะมันมีค่าเท่ากัน?

ตัวแปรจำนวนเต็มที่มีค่า 21 จะต้องไม่แตกต่างจากตัวแปรจำนวนเต็มตัวอื่นซึ่งมีค่าเท่ากับ 21 เช่นกัน ง่ายๆ แค่นั้นเอง ???

การไม่มีอัตลักษณ์ทำให้เกิดข้อได้เปรียบอีกประการหนึ่ง:ถ้าคุณคิดในทางปฏิบัติ คุณสามารถจินตนาการได้ว่าคุณไม่มีตัวตน จากนั้นใครก็ตามที่มีลักษณะเหมือนกันสามารถแทนที่หรือแทนที่คุณได้ ???

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

แต่สำหรับประเภทค่านิยม พวกเขาไม่มีอัตลักษณ์และเป็นประโยชน์ต่อพวกเขา ?

ประโยชน์ของการใช้ประเภทมูลค่ามีอะไรบ้าง

? ไม่มีเงื่อนไขการแข่งขันและการหยุดชะงัก:?

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

⚔️ ไม่มีรอบการกัก:⚔️

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

?‍?‍?‍? การนับการอ้างอิงอัตโนมัติ:?‍?‍?‍?

สำหรับประเภทการอ้างอิง Swift ใช้การนับการอ้างอิงอัตโนมัติเพื่อติดตามวัตถุที่ใช้งานอยู่หรือที่ใช้งานอยู่ทั้งหมด และจัดสรรคืนอินสแตนซ์เฉพาะเมื่อไม่มีการอ้างอิงที่รัดกุมแล้วเท่านั้น หากเราคิดสักนิด เราสามารถพูดได้ว่าเป็นการปฏิบัติการที่หนักหน่วงเพราะ Swift Runtime จำเป็นต้องติดตามวัตถุอยู่เสมอ แต่เนื่องจากประเภทค่าถูกจัดสรรในสแต็ก จึงไม่จำเป็นต้องมี ARC จึงถูกและเร็วกว่า??.

แต่เดี๋ยวก่อน...มันจัดการหน่วยความจำสำหรับ Array, Dictionary และ String อย่างไร

เนื่องจากเราไม่สามารถทราบขนาดที่แท้จริงของอาร์เรย์ พจนานุกรม และสตริงในขณะคอมไพล์ได้ จึงไม่มีขอบเขตสำหรับการจัดสรรในเวลาคอมไพล์ แม้ว่าจะเป็นประเภทค่าภายใน แต่ก็ไม่สามารถจัดสรรในสแต็กได้ พวกเขาจำเป็นต้องได้รับการจัดสรรในหน่วยความจำฮีป และในการจัดการสิ่งนี้ Swift มาพร้อมกับ คัดลอกในการเขียน .?

แต่นี่คืออะไร??

เมื่อเราบอกว่าอินสแตนซ์หนึ่งเป็นสำเนาของอีกอินสแตนซ์หนึ่ง นี่หมายความว่าอินสแตนซ์เหล่านั้นเหมือนกัน มีค่าเท่ากัน แต่ใน Swift สำหรับประเภทข้างต้นเหล่านี้ (อาร์เรย์ พจนานุกรม สตริง ฯลฯ) สำเนาจริงจะถูกสร้างขึ้นบนฮีปก็ต่อเมื่ออินสแตนซ์ถูกกลายพันธุ์เท่านั้น นี่เรียกว่าเทคนิคการเพิ่มประสิทธิภาพสำหรับประเภทค่า???

บทสรุป

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

ดังนั้นแทนที่จะต่อสู้กับประเภทมูลค่ากับประเภทอ้างอิง ให้ใช้อย่างชาญฉลาด

??? ไชโย !!! ขอบคุณสำหรับการอ่าน!! ???

✅✅✅คุณสามารถหาฉันได้ที่ ทวิตเตอร์ .✅✅✅