รัฐอะไรรัฐที่เปลี่ยนแปลงไม่ได้และรัฐที่ไม่เปลี่ยนรูป?


32

นี่เป็นคำถามสำหรับมือใหม่ แต่ฉันไม่พบคำตอบที่เพียงพอสำหรับมือใหม่ใน Google

ผู้คนหมายถึงอะไรเมื่อพวกเขาพูดว่า 'state' - ในการเขียนโปรแกรมโดยทั่วไปและในการเขียนโปรแกรม OO โดยเฉพาะ?

นอกจากนี้รัฐที่ไม่แน่นอนและไม่แน่นอนคืออะไร - อีกครั้งโดยทั่วไปในการเขียนโปรแกรมและยังเฉพาะใน OOP?


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

คำตอบ:


46

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

ตัวอย่างเช่นหมายเลข 10 ด้วยตัวเองไม่ได้เป็นตัวแทนของรัฐใด ๆ : มันเป็นเพียงตัวเลขที่กำหนดไว้อย่างดีและมักจะเป็นตัวเอง: จำนวนธรรมชาติ 10 เป็นอีกตัวอย่างหนึ่งสตริง "HELLO" เป็นลำดับห้าตัวอักษรและ มันถูกอธิบายอย่างสมบูรณ์โดยตัวละครที่บรรจุอยู่และลำดับที่ปรากฏ ในห้าล้านปีต่อจากนี้สตริง "HELLO" จะยังคงเป็นสตริง "HELLO": มูลค่าที่แท้จริง

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

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

("colour", "blue")

กับรถของฉัน คู่ ("สี", "สีฟ้า") เป็นค่าบริสุทธิ์ที่อธิบายสถานะของรถคันนั้น

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

("colour", "blue")

พรุ่งนี้ฉันจะให้มันทาสีใหม่ในที่มืดและสถานะใหม่จะเป็น

("colour", "black")

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

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

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

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

ข้อดี / ข้อเสียของทั้งสองวิธี

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

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

2
@Doval: คุณสามารถนึกถึงสถานะโลกเป็นสถานะของวัตถุทั่วโลก เท่าที่ฉันรู้มุมมองนี้จะใช้เช่นในทับทิม ฟังก์ชั่นที่จำสถานะเป็น isomorphic ให้กับวัตถุด้วยวิธีการเดียว แนวคิดพื้นฐานทั่วไปคือคุณเชื่อมโยงค่ากับข้อมูลประจำตัวหรือสถานที่นั่นคือบางสิ่งสามารถเก็บค่าได้ (อาจเป็นค่าที่ไม่แน่นอน) แต่คงไว้ซึ่งเอกลักษณ์
Giorgio

3
แน่นอนว่าฉันเห็นด้วยในหลักการ ฉันแค่ทำให้แน่ใจว่า Prog เข้าใจว่าการเป็นรัฐไม่ใช่สิ่งที่พิเศษสำหรับ OOP ฉันไม่คิดว่า "ทุกอย่างเป็นวัตถุ" แนวความคิดมาโดยธรรมชาติ
Doval

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

11

สถานะเป็นเพียงข้อมูลเกี่ยวกับสิ่งที่เก็บไว้ในหน่วยความจำ

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

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

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

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


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

ขอบคุณสำหรับคำตอบ. ดังนั้นโดยทั่วไปใน OOP เมื่อมีคนพูดว่า 'รัฐ' พวกเขามักจะหมายถึง "ตัวแปรสมาชิกของวัตถุ"? ถ้าเป็นเช่นนั้น 'สถานะที่เปลี่ยนแปลงไม่ได้' เป็นตัวแปรสาธารณะหรือพบได้ทั่วไปใน OOP ตัวแปรส่วนตัวที่สามารถเปลี่ยนแปลงได้ด้วยวิธีการตั้งค่า - ในขณะที่ 'สถานะที่ไม่เปลี่ยนรูป' เป็นเพียงตัวแปรสมาชิกส่วนตัวหรือไม่
Aviv Cohn

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

1
ฉันคิดว่ารัฐเป็นมูลค่าของทรัพย์สินบางส่วนของหน่วยงานบางอย่าง "จัดส่ง" เป็นสถานะ ดังนั้นคือ "อัตราภาษี" น้ำหนักของบางสิ่งเป็นสถานะ ไม่ว่าคุณจะตื่นหรือนอนหลับอยู่ในสถานะ สีของบางสิ่งบางอย่างเป็นสถานะ ข้อมูลที่มีความหมายเกี่ยวกับบางสิ่งบางอย่างซึ่งจัดเก็บอยู่ในหน่วยความจำคอมพิวเตอร์บางประเภท
Robert Harvey

1
ในหลายภาษาการเปลี่ยนแปลงไม่ได้สามารถบังคับใช้โดยการประกาศตัวแปรสมาชิกเป็น "const" หรือ "final" ตัวแปรดังกล่าวสามารถเริ่มต้นได้โดยผู้สร้าง อย่าคิดว่าตัวแปรส่วนตัวนั้นไม่สามารถเปลี่ยนแปลงได้ - พวกมันยังสามารถแก้ไขได้โดยฟังก์ชั่นสมาชิกของคลาส (เมธอด)
Simon B

7

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

Stateful vs Stateless

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

ตัวอย่างเช่น OpenGL นั้นน่าจะเป็น API ที่มีชื่อเสียงที่สุดที่ฉันรู้จัก หากฉันอาจพูดเกินจริงอย่างน่าหัวเราะสักครู่เราอาจพูดว่ามันเป็นดังนี้:

glSetCurrentVertexBufferArray(vba1);
glSetCurrentVertexBufferObject(vbo1);
glSetCurrentVertexShader(vert1);
glSetCurrentFragmentShader(frag1);
// a dozen other things
glActuallyDrawStuffWithCurrentState(GL_TRIANGLES);

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

OpenGL รุ่นที่ไร้สัญชาติ (มีขนาดใหญ่เกินไป) อาจมีลักษณะเช่นนี้:

glActuallyDrawStuff(vba1, vbo1, vert1, frag1, /* a dozen other things */, GL_TRIANGLES);

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

ไม่แน่นอน vs ไม่เปลี่ยนรูป

เท่าที่ผมทราบความแตกต่างนี้มีความหมายเฉพาะเมื่อคุณสามารถระบุสถานะเริ่มต้น ตัวอย่างเช่นการใช้ตัวสร้าง C ++:

// immutable state
ImmutableWindow windowA = new ImmutableWindow(600, 400);
windowA = new ImmutableWindow(800, 600); // to change the size, I need a whole new window

// mutable state
MutableWindow windowB = new MutableWindow(600, 400);
windowB.width = 800; // to change the size, I just alter the existing object
windowB.height = 600;

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

PSใน OOP มันเป็นความจริงที่ "state" มักจะหมายถึง "ตัวแปรสมาชิก" แต่มันอาจจะมากกว่านั้น ตัวอย่างเช่นใน C ++ เมธอดสามารถมีตัวแปรแบบสแตติกและ lambdas สามารถปิดได้โดยการจับตัวแปร ในทั้งสองกรณีตัวแปรเหล่านั้นยังคงมีอยู่ในการเรียกใช้ฟังก์ชันหลายครั้งและอาจมีคุณสมบัติเป็นสถานะ ตัวแปรท้องถิ่นในฟังก์ชั่นปกติอาจได้รับการพิจารณาสถานะขึ้นอยู่กับวิธีที่พวกเขาใช้ (คนที่ฉันมีใน main () มักนับ)


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

2

ในคำพูดของคนธรรมดา

พจนานุกรมฯ :

เงื่อนไขหรือโหมดของความเป็นอยู่โดยคำนึงถึงสถานการณ์

  1. state - สิ่งที่เป็นสิ่งที่เกี่ยวกับคุณสมบัติหลักของมัน;

สถานะของบางสิ่งบางอย่างคือชุดของค่าที่แอตทริบิวต์มีในช่วงเวลาใดก็ตาม

ใน OOP สถานะของวัตถุคือสแน็ปช็อตของค่าคุณลักษณะของมันในช่วงเวลาใด ๆ

Thing t = new Thing();
t.setColor("blue");
t.setPrice(100)
t.setSize("small");

สถานะของมันคือสีของมันคือสีน้ำเงินราคาของมันคือ 100 และขนาดของมันเล็ก

หากคุณทำภายหลัง:

t.setColor("red");

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

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

Thing t = new Thing("red",100,"small");
t.setColor("blue") -->> ERROR, the programmer didn't provide a setter or any other way to change the properties values after initialization.

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

Thing t = new Thing("red",100,"small");
t = new Thing("blue",100,"small");
// I had to create a new Thing with another color since this thing is inmutable.
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.