วัตถุที่เปลี่ยนแปลงไม่ได้และไม่เปลี่ยนรูป


173

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


stringเป็นสิ่งที่เปลี่ยนแปลงไม่ได้อย่างน้อยใน. NET และฉันคิดว่าในภาษาที่ทันสมัยอื่น ๆ อีกมากมายเช่นกัน
Domenic

4
มันขึ้นอยู่กับสิ่งที่สตริงเป็นจริงในภาษา - สตริง 'erlang' เป็นเพียงอาร์เรย์ของ ints และ Haskell "สตริง" เป็นอาร์เรย์ของตัวอักษร
Chii

4
สตริงทับทิมเป็นอาร์เรย์ไบต์ที่ไม่แน่นอน ผลักดันฉันถั่วอย่างแน่นอนว่าคุณสามารถเปลี่ยนพวกเขาในสถานที่
Daniel Spiewak

6
แดเนียล - ทำไม คุณพบว่าตัวเองกำลังทำมันโดยบังเอิญหรือไม่?

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

คำตอบ:


162

ทีนี้มันมีแง่มุมสองสามอย่าง

  1. วัตถุที่ไม่แน่นอนที่ไม่มีการอ้างอิงตัวตนสามารถทำให้เกิดข้อผิดพลาดในเวลาที่ผิดปกติ ตัวอย่างเช่นพิจารณาPersonbean ที่มีequalsเมธอดตามค่า:

    Map<Person, String> map = ...
    Person p = new Person();
    map.put(p, "Hey, there!");
    
    p.setName("Daniel");
    map.get(p);       // => null
    

    Personอินสแตนซ์ที่ได้รับ "หายไป" ในแผนที่เมื่อใช้เป็นสำคัญเพราะhashCodeความเสมอภาคและมีพื้นฐานอยู่บนค่าแน่นอน ค่าเหล่านั้นเปลี่ยนไปนอกแผนที่และคร่ำครวญทั้งหมดล้าสมัยแล้ว นักทฤษฎีชอบที่จะพิณในจุดนี้ แต่ในทางปฏิบัติฉันไม่พบว่ามันเป็นปัญหามากเกินไป

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

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

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

ด้วยที่กล่าวว่าฉันไม่ค่อยกระตือรือร้นในเรื่องนี้ ปัญหาบางอย่างไม่ได้เป็นแบบอย่างเมื่อทุกอย่างไม่เปลี่ยนรูป แต่ฉันคิดว่าคุณควรพยายามที่จะผลักดันโค้ดของคุณให้มากที่สุดเท่าที่จะเป็นไปได้โดยสมมติว่าคุณใช้ภาษาซึ่งทำให้ความคิดเห็นที่เชื่อถือได้ (C / C ++ ทำให้ยากเช่นเดียวกับ Java) . กล่าวโดยย่อ: ข้อดีขึ้นอยู่กับปัญหาของคุณบ้าง แต่ฉันมักจะชอบความไม่เปลี่ยนรูป


11
การตอบสนองที่ยอดเยี่ยม คำถามเล็ก ๆ ข้อหนึ่ง: C ++ ไม่ได้รับการสนับสนุนที่ดีสำหรับความไม่สามารถเปลี่ยนแปลงได้หรือไม่? คุณสมบัติความถูกต้องของconstไม่เพียงพอหรือไม่
Dimitri C.

1
@DimitriC: C ++ จริง ๆ แล้วมีคุณสมบัติพื้นฐานบางอย่างที่เด่นชัดที่สุดคือความแตกต่างที่ดีขึ้นระหว่างที่เก็บสินค้าที่ควรจะสรุปสถานะไม่ได้ใช้งานร่วมกันจากสิ่งที่ห่อหุ้มตัวตนของวัตถุ
supercat

2
ในกรณีของการเขียนโปรแกรม Java Joshua Bloch นำคำอธิบายที่ดีเกี่ยวกับหัวข้อนี้ในหนังสือที่มีชื่อเสียงของเขาEffective Java (รายการ 15)
dMathieuD

27

วัตถุที่เปลี่ยนไม่ได้กับคอลเลกชันที่ไม่เปลี่ยนรูป

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

คอลเลกชันที่ไม่เปลี่ยนรูปคือชุดที่ไม่เคยเปลี่ยนแปลง

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

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

การใช้งานที่ชาญฉลาดไม่จำเป็นต้องคัดลอก (โคลน) การรวบรวมทั้งหมดเพื่อให้การเปลี่ยนแปลงไม่ได้ ตัวอย่างที่ง่ายที่สุดคือสแต็กที่นำมาใช้เป็นรายการที่เชื่อมโยงเดี่ยวและการดำเนินการพุช / ป๊อป คุณสามารถนำโหนดทั้งหมดกลับมาใช้ใหม่จากคอลเลกชันก่อนหน้านี้ในคอลเลกชันใหม่โดยเพิ่มเพียงโหนดเดียวสำหรับการพุชและไม่โคลนโหนดสำหรับป๊อปอัพ การดำเนินการ push_tail ในรายการที่เชื่อมโยงเดี่ยวไม่ง่ายหรือมีประสิทธิภาพ

ตัวแปร / การอ้างอิงที่เปลี่ยนแปลงไม่ได้กับ Mutable

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

  • ใน Erlang สิ่งนี้เป็นจริงสำหรับ "ตัวแปร" ทั้งหมด ฉันสามารถกำหนดวัตถุให้กับการอ้างอิงได้เพียงครั้งเดียว ถ้าฉันจะดำเนินการกับคอลเลกชันฉันจะไม่สามารถมอบหมายคอลเลกชันใหม่ให้กับการอ้างอิงเก่า (ชื่อตัวแปร)
  • สกาล่ายังสร้างสิ่งนี้เป็นภาษาที่มีการอ้างอิงทั้งหมดที่ถูกประกาศด้วยvarหรือval , vals เป็นการมอบหมายเพียงครั้งเดียวและส่งเสริมสไตล์การทำงาน แต่ vars ช่วยให้โครงสร้างโปรแกรม C-like หรือ Java-like มากขึ้น
  • ต้องการการประกาศ var / val ในขณะที่ภาษาดั้งเดิมหลายภาษาใช้ตัวดัดแปลงเสริมเช่นสุดท้ายใน java และconstใน C

ความง่ายในการพัฒนาเทียบกับประสิทธิภาพ

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

ข้อเสียเปรียบหลักคือประสิทธิภาพ นี่คือบทความเกี่ยวกับการทดสอบอย่างง่ายที่ฉันทำใน Javaเปรียบเทียบวัตถุที่ไม่เปลี่ยนรูปและไม่แน่นอนในปัญหาของเล่น

ปัญหาด้านประสิทธิภาพเป็นสิ่งที่สงสัยในหลาย ๆ แอปพลิเคชั่น แต่ไม่ใช่ทั้งหมดซึ่งเป็นสาเหตุที่ทำให้แพคเกจตัวเลขจำนวนมากเช่นคลาส Numpy Array ใน Python อนุญาตให้มีการอัปเดต In-Place ของอาร์เรย์ขนาดใหญ่ สิ่งนี้จะมีความสำคัญสำหรับพื้นที่แอปพลิเคชันที่ใช้ประโยชน์จากเมทริกซ์ขนาดใหญ่และการดำเนินการเวกเตอร์ ปัญหาข้อมูลขนาดใหญ่แบบขนานและการคำนวณอย่างเข้มข้นช่วยให้สามารถเร่งความเร็วได้อย่างยอดเยี่ยมด้วยการใช้งานในสถานที่


12

ตรวจสอบการโพสต์บล็อกนี้: http://www.yegor256.com/2014/06/09/objects-should-be-immutable.html มันอธิบายว่าทำไมวัตถุที่ไม่เปลี่ยนรูปนั้นดีกว่าไม่แน่นอน ในระยะสั้น:

  • วัตถุที่ไม่เปลี่ยนรูปนั้นง่ายต่อการสร้างทดสอบและใช้งาน
  • วัตถุที่ไม่เปลี่ยนรูปอย่างแท้จริงมักจะปลอดภัยต่อเธรด
  • มันช่วยหลีกเลี่ยงการแต่งงานแบบชั่วคราว
  • การใช้งานไม่มีผลข้างเคียง (ไม่มีการป้องกันสำเนา)
  • หลีกเลี่ยงปัญหาความไม่แน่นอนของข้อมูลเฉพาะตัว
  • พวกเขามักจะมีความล้มเหลวของอะตอมมิก
  • แคชง่ายกว่ามาก

10

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

คุณสามารถใช้พวกมันสำหรับวัตถุระดับต่ำไม่ใช่โพลิมอร์ฟิคเช่นคลาส CPoint ซึ่งส่วนใหญ่จะใช้กับซีแมนทิกส์ตามตัวอักษร

หรือคุณสามารถใช้พวกมันสำหรับอินเทอร์เฟซ polymorphic ระดับสูง - เช่น IFunction ซึ่งเป็นตัวแทนของฟังก์ชันทางคณิตศาสตร์ - ซึ่งใช้เฉพาะกับซีแมนทิกส์ของวัตถุ

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

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

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


ฉันคิดว่าฉันเข้าใจผิดส่วนที่ 4 เพื่อประโยชน์ที่ยิ่งใหญ่ที่สุด: ความไม่สามารถเปลี่ยนแปลงได้ + ความหมายของวัตถุ + ตัวชี้สมาร์ททำให้การเป็นเจ้าของวัตถุเป็นจุด "moot" ดังนั้นจึงเป็นที่ถกเถียงกันอยู่? ฉันคิดว่าคุณกำลังใช้ "moot" ไม่ถูกต้อง ... การเห็นว่าประโยคถัดไปคือวัตถุมีนัย "พฤติกรรมที่กำหนดขึ้นแล้ว" จากพฤติกรรม "moot" (ที่ถกเถียงกัน)
Benjamin

คุณพูดถูกฉันใช้ 'ดำริ' ไม่ถูกต้อง พิจารณาเปลี่ยน :)
QBziZ

6

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


คุณกำลังแนะนำว่าเธรดมีการพันกันยุ่ง? ค่อนข้างยืด :) จริง ๆ แล้วกระทู้ถ้าคุณคิดเกี่ยวกับมันค่อนข้างใกล้จะถูกทอดทิ้ง การเปลี่ยนแปลงที่เธรดหนึ่งทำให้มีผลต่ออีก +1
ndrewxie

4

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

ฉันไม่คิดว่าจะมีคำตอบที่ชัดเจนว่าคำตอบไหนดีกว่าสำหรับทุกสถานการณ์ พวกเขาทั้งสองมีที่ของพวกเขา


1

หากประเภทคลาสนั้นไม่แน่นอนตัวแปรของประเภทคลาสนั้นอาจมีความหมายต่างกันจำนวนหนึ่ง ตัวอย่างเช่นสมมติว่าวัตถุfooมีเขตข้อมูลint[] arrและมีการอ้างอิงไปint[3]ยังหมายเลข {5, 7, 9} แม้ว่าจะรู้ชนิดของฟิลด์ แต่ก็มีอย่างน้อยสี่อย่างที่สามารถเป็นตัวแทนได้:

  • การอ้างอิงที่อาจเป็นแบบแบ่งใช้ซึ่งผู้ถือทั้งหมดจะสนใจเพียงว่ามันห่อหุ้มค่า 5, 7 และ 9 หากfooต้องการarrห่อหุ้มค่าที่แตกต่างกันมันจะต้องแทนที่ด้วยอาร์เรย์ที่ต่างกันซึ่งมีค่าที่ต้องการ หากใครต้องการทำสำเนาfooหนึ่งอาจให้สำเนาทั้งอ้างอิงarrหรืออาร์เรย์ใหม่ที่ถือค่า {1,2,3} แล้วแต่จำนวนใดจะสะดวกกว่า

  • การอ้างอิงเดียวทุกที่ในจักรวาลไปยังอาเรย์ที่ห่อหุ้มค่า 5, 7 และ 9. ชุดของที่เก็บข้อมูลสามแห่งซึ่งในขณะนี้เก็บค่าไว้ที่ 5, 7 และ 9; ถ้าfooต้องการให้แค็ปซูลค่า 5, 8, และ 9 มันอาจเปลี่ยนไอเท็มที่สองในอาร์เรย์นั้นหรือสร้างอาเรย์ใหม่ที่เก็บค่า 5, 8 และ 9 และละทิ้งอันเก่า โปรดทราบว่าหากมีใครต้องการทำสำเนาfooหนึ่งจะต้องในการคัดลอกแทนที่arrด้วยการอ้างอิงถึงอาร์เรย์ใหม่เพื่อที่foo.arrจะยังคงเป็นเพียงการอ้างอิงไปยังอาร์เรย์นั้นทุกที่ในจักรวาล

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

  • การอ้างอิงไปยังอาร์เรย์ซึ่งfooเป็นเจ้าของ แต่เพียงผู้เดียว แต่การอ้างอิงที่ถูกเก็บไว้โดยวัตถุอื่นด้วยเหตุผลบางอย่าง (เช่นต้องการมีวัตถุอื่นเพื่อเก็บข้อมูลที่นั่น - flipside ของกรณีก่อนหน้า) ในสถานการณ์สมมตินี้arrสรุปทั้งตัวตนของอาร์เรย์และเนื้อหา การแทนที่arrด้วยการอ้างอิงไปยังอาร์เรย์ใหม่จะเปลี่ยนความหมายทั้งหมด แต่การมีการarrอ้างอิงแบบโคลนนิ่งfoo.arrจะเป็นการละเมิดสมมติฐานที่fooเป็นเจ้าของ แต่เพียงผู้เดียว fooมีจึงเป็นวิธีการที่จะคัดลอกไม่มี

ในทางทฤษฎีint[]ควรเป็นประเภทที่เรียบง่าย แต่มีความหมายที่แตกต่างกันสี่แบบ ในทางตรงกันข้ามการอ้างอิงไปยังวัตถุที่ไม่เปลี่ยนรูป (เช่นString) โดยทั่วไปมีเพียงหนึ่งความหมาย "อำนาจ" ของวัตถุที่ไม่เปลี่ยนรูปแบบส่วนใหญ่เกิดจากข้อเท็จจริงนั้น


1

อินสแตนซ์ที่ไม่แน่นอนถูกส่งผ่านโดยการอ้างอิง

อินสแตนซ์ที่ไม่เปลี่ยนรูปจะถูกส่งผ่านโดยค่า

ตัวอย่างนามธรรม สมมติว่ามีไฟล์ชื่อtxtfileอยู่ใน HDD ของฉัน ตอนนี้เมื่อคุณถามtxtfileจากฉันฉันสามารถคืนมันในสองโหมด:

  1. สร้างทางลัดไปยังtxtfileและทางลัดไปยังคุณหรือ
  2. นำสำเนาสำหรับtxtfileและส่งสำเนาถึงคุณ

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

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


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

0

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


0

วิธีที่ไม่เปลี่ยนรูปนั้นไม่สามารถเปลี่ยนแปลงได้และหมายความว่าคุณสามารถเปลี่ยนแปลงได้

วัตถุแตกต่างจากดั้งเดิมใน Java Primitives ถูกสร้างขึ้นในประเภท (บูลีน, int, ฯลฯ ) และวัตถุ (คลาส) เป็นประเภทที่ผู้ใช้สร้างขึ้น

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

ผู้คนจำนวนมากคิดว่าตัวแปรพื้นฐานและตัวแปรออบเจ็กต์ที่มีตัวดัดแปลงสุดท้ายที่อยู่ข้างหน้านั้นไม่เปลี่ยนรูป แต่สิ่งนี้ไม่เป็นความจริง ดังนั้นสุดท้ายก็ไม่ได้หมายความว่าตัวแปรจะเปลี่ยนแปลงไม่ได้ ดูตัวอย่างที่นี่http://www.siteconsortium.com/h/D0000F.php


0

Immutable object- เป็นสถานะวัตถุซึ่งไม่สามารถเปลี่ยนแปลงได้หลังจากการสร้าง วัตถุไม่เปลี่ยนรูปเมื่อเขตข้อมูลทั้งหมดไม่เปลี่ยนรูป

ด้ายปลอดภัย

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

ผลข้างเคียงฟรี

ในฐานะนักพัฒนาคุณมั่นใจอย่างสมบูรณ์ว่าสถานะของวัตถุที่ไม่เปลี่ยนรูปไม่สามารถเปลี่ยนแปลงได้จากที่ใด ๆ (ตามวัตถุประสงค์หรือไม่)

รวบรวมการเพิ่มประสิทธิภาพ

ปรับปรุงประสิทธิภาพ

ข้อด้อย:

การคัดลอกวัตถุเป็นการดำเนินการที่หนักกว่าการเปลี่ยนวัตถุที่ไม่แน่นอนซึ่งเป็นสาเหตุที่ทำให้ประสิทธิภาพการทำงานลดลง

ในการสร้างimmutableวัตถุคุณควรใช้:

  1. ระดับภาษา แต่ละภาษามีเครื่องมือที่จะช่วยคุณ ตัวอย่างเช่นมี Java finalและprimitivesรวดเร็วมีletและ[เกี่ยวกับ]struct ภาษากำหนดประเภทของตัวแปร ยกตัวอย่างเช่น Java มีprimitiveและreferenceชนิดสวิฟท์มีvalueและreferenceประเภท[เกี่ยวกับ] สำหรับออบเจ็กต์ที่ไม่เปลี่ยนรูปได้จะสะดวกกว่าprimitivesและเป็นvalueชนิดที่ทำสำเนาโดยค่าเริ่มต้น สำหรับreferenceประเภทมันยากกว่า (เพราะคุณสามารถเปลี่ยนสถานะของวัตถุได้) แต่เป็นไปได้ ตัวอย่างเช่นคุณสามารถใช้cloneรูปแบบในระดับนักพัฒนา

  2. ระดับนักพัฒนา ในฐานะนักพัฒนาคุณไม่ควรมีส่วนต่อประสานสำหรับการเปลี่ยนสถานะ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.