จุดของคุณสมบัติคืออะไร?


11

นี่คือข้อโต้แย้งบางประการสำหรับคุณสมบัติและข้อโต้แย้งของฉัน:

ใช้งานง่ายกว่าการเขียนวิธี getter และ setter

คู่ของ Getter และ setter เป็นกลิ่นของโค้ด การทำให้ง่ายต่อการเขียนสิ่งเหล่านี้ก็เหมือนกับการทำให้ล้มเหลวในการทดสอบคณิตศาสตร์โดยใช้แบบฟอร์ม Scantron และเติมใน 'C's ทั้งหมด วัตถุที่มีเพียงสถานะสำหรับการคงอยู่ไม่ควรใช้ getters / setters และควรสร้างวัตถุที่ไม่เปลี่ยนรูปในเวลาที่มีอยู่

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

พวกเขาให้ข้อบ่งชี้ประสิทธิภาพอย่างคร่าว ๆ กับผู้บริโภค

นี่คือสิ่งที่สามารถเปลี่ยนแปลงได้ในอนาคตสำหรับอสังหาริมทรัพย์ใด ๆ ก็ตาม สมมติว่าในรีลีส 1.0 การเข้าถึง PropertyX จะส่งคืนฟิลด์ ในรีลีส 1.5 หากฟิลด์เป็นโมฆะ PropertyX จะใช้รูปแบบวัตถุ Null เพื่อสร้างวัตถุ null ใหม่ ในรุ่น 2.0 ฟิลด์จะได้รับการตรวจสอบเพิ่มเติมโดยวิธี getter ใน PropertyX

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

มันดีกว่าทุ่งสาธารณะ

นี่เป็นเรื่องจริง แต่เป็นวิธีการ

พวกเขาเป็นตัวแทนด้านที่แตกต่างกันโดยพื้นฐานของวัตถุกว่าวิธีการและผู้บริโภคของวัตถุควรใส่ใจเกี่ยวกับเรื่องนี้

คุณแน่ใจหรือว่าข้อความทั้งสองข้างต้นเป็นจริง

พวกเขาพิมพ์ง่ายกว่าผู้ชาย

แน่นอนว่าการพิมพ์myObject.Lengthนั้นง่ายกว่าการพิมพ์myObject.Length()แต่ไม่สามารถแก้ไขได้ด้วยน้ำตาลประโยคเล็กน้อย


ทำไมต้องใช้วิธีการแทนคุณสมบัติ?

  • ไม่รับประกันประสิทธิภาพ API จะยังคงเป็นจริงแม้ว่าวิธีการจะซับซ้อนมากขึ้น ผู้บริโภคจะต้องโปรไฟล์รหัสของพวกเขาหากพวกเขากำลังทำงานในปัญหาประสิทธิภาพการทำงานและไม่พึ่งพา word-of-API

  • น้อยกว่าสำหรับผู้บริโภคที่จะคิดเกี่ยวกับ สถานที่ให้บริการนี้มี setter หรือไม่? วิธีการที่แน่นอนไม่ได้

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

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


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

(ความคิดเหล่านี้มาถึงฉันหลังจากคิดถึง CQS)


5
+1 คุณสมบัติเป็นวิธีการที่มีไวยากรณ์ของฟิลด์และนั่นก็ไม่สมเหตุสมผล
Nemanja Trifunovic

23
@Nemanja Trifunovic: มันสมเหตุสมผลดีถ้าคุณเขียนtype GetFoo() void SetFoo()หมื่นครั้ง ตลอดเวลาที่ฉันเขียนรหัส C # ฉันไม่เคยสับสนกับทรัพย์สิน
Ed S.

23
ฟังดูเหมือนว่าคุณได้ตัดสินใจแล้ว คำถามคืออะไร?
Dean Harding

9
@Nemanja Trifunovic: "Getters and setters นั้นแย่มาก"คุณสามารถทำซ้ำได้หลายครั้งเท่าที่คุณต้องการ แต่มันจะไม่ทำให้เป็นจริง อธิบายเกี่ยวกับสาเหตุที่คุณคิดว่าพวกเขาไม่ดีได้อย่างไร เท่าที่เกิดปัญหาดังนั้นเนื่องจากการพิมพ์ชื่อคุณสมบัติแทนชื่อตัวแปรพื้นฐานที่เป็นไปไม่ได้ที่จะพลาดข้อผิดพลาดพิจารณามันจะผิดพลาดคุณโปรแกรมทันทีที่คุณเรียกคุณสมบัติและมันค่อนข้างหายาก เมื่อมันเกิดขึ้นฉันรู้ว่าสิ่งที่ฉันจะทำให้มันและฉันได้รับการแก้ไขในสองวินาที ฉันไม่เห็นปัญหา
Ed S.

3
เพียงแค่ผ่านไปชี้ให้ @NemanjaTrifunovic ว่าทำไมทะเยอทะยานและหมาวิธีการชั่วบทความค่อนข้างเก่าเป็นเรื่องเกี่ยวกับJavaและขีดเส้นใต้ความอ่อนแอ Java : ความอ่อนแอของไม่ได้มีคุณสมบัติ (ดังนั้นจึงแสดงรายละเอียดการใช้งานมากเกินไป) ... กัดหางของเราที่นี่ (มันควรจะเป็นชื่อgetters และ setters นั้นไม่ดีในจาวาเพราะเราไม่มีมาตรฐานความคิดดีๆเกี่ยวกับสิ่งเหล่านั้น )
ZJR

คำตอบ:


44

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

คู่ของ Getter และ setter เป็นกลิ่นของโค้ด

ไม่จำเป็นว่าฉันต้องเถียง แต่อย่างใดนี่ไม่ใช่เรื่องของ getters / setters เทียบกับคุณสมบัติ แต่ควรพิจารณาว่าควรใช้ด้วยหรือไม่ นอกจากนี้โปรดทราบว่าคุณสามารถออกจากsetXส่วนเช่นเดียวกับที่คุณสามารถสร้างคุณสมบัติแบบอ่านอย่างเดียว

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

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

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

[วิธีการมี] ไม่มีการรับรองประสิทธิภาพ API จะยังคงเป็นจริงแม้ว่าวิธีการจะซับซ้อนมากขึ้น ผู้บริโภคจะต้องโปรไฟล์รหัสของพวกเขาหากพวกเขากำลังทำงานในปัญหาประสิทธิภาพการทำงานและไม่พึ่งพา word-of-API

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

แน่นอนว่าการพิมพ์ myObject.Length นั้นง่ายกว่าการพิมพ์ myObject.Length () แต่ไม่สามารถแก้ไขด้วยน้ำตาล syntactic เล็กน้อยได้หรือไม่

สรรพคุณคือน้ำตาลซินแทคติค

น้อยกว่าสำหรับผู้บริโภคที่จะคิดเกี่ยวกับ สถานที่ให้บริการนี้มี setter หรือไม่? วิธีการที่แน่นอนไม่ได้

"มีผู้ตั้งตัวให้ทะเยอทะยานนี้หรือไม่?" ความแตกต่างเดียวกัน

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

ฉันไม่แน่ใจว่าคุณกำลังพยายามที่จะบอกเราที่นี่ สำหรับคุณสมบัติมีกฎหมายที่ไม่ได้เขียนไว้อย่างดีกว่าเพื่อไม่ให้เกิดผลข้างเคียง


3
+1 และไม่ใช่กฎหมายที่ไม่ได้เขียนไว้ แนวทางการใช้งานคุณสมบัติบน MSDN ได้เขียนไว้กับคนอื่น ๆ ฉันคิดว่า OP ควรผ่านพวกเขาเพื่อทำให้ตัวเองชัดเจนจากข้อสงสัยมากมาย และฉันไม่สามารถโพสต์ลิงค์ที่นี่ตั้งแต่ฉันเขียนสิ่งนี้จากโทรศัพท์ของฉัน แต่แนวทางควรจะง่ายต่อการค้นหา
decyclone


@delnan: สรรพคุณไม่ใช่น้ำตาลซินแทคติค คุณสมบัติสามารถถือว่าเป็นฟิลด์ (สามารถใช้เป็นเป้าหมายการกำหนดได้หากมี setter) วิธีการไม่สามารถ
xofz

1
@SamPearson: obj.x = yแมปไปobj.setX(y)และแมปไปobj.x obj.getX()มันแตกต่างกันอย่างไร

1
@ SamPearson คุณสามารถเปลี่ยนการมองเห็นของ setter คุณสมบัติและทะเยอทะยานเป็นอิสระจากกัน ฉันใช้สิ่งนี้ตลอดเวลากับอ็อบเจกต์ Entity Framework ของฉัน: setters ของฉันได้รับการปกป้อง (ดังนั้นเฟรมเวิร์กเท่านั้นที่สามารถกำหนดค่า) ดังนั้นจึงเป็นไปได้อย่างสมบูรณ์แบบที่จะพูด int length = myObject.Length โดยไม่อนุญาตให้ myObject.Length = 10
Michael Brown

19

คู่ของ Getter และ setter เป็นกลิ่นของโค้ด

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

นี่คือสิ่งที่สามารถเปลี่ยนแปลงได้ในอนาคตสำหรับอสังหาริมทรัพย์ใด ๆ ก็ตาม สมมติว่าในรีลีส 1.0 การเข้าถึง PropertyX จะส่งคืนฟิลด์ ในรีลีส 1.5 หากฟิลด์เป็นโมฆะ PropertyX จะใช้รูปแบบวัตถุ Null เพื่อสร้างวัตถุ null ใหม่ ในรุ่น 2.0 ฟิลด์จะได้รับการตรวจสอบเพิ่มเติมโดยวิธี getter ใน PropertyX

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

ดูเหมือน API ที่ออกแบบมาไม่ดีฉันไม่เห็นว่าเป็นความผิดของไวยากรณ์คุณสมบัติ

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


1
ฉันจะให้รางวัลเพื่อให้ได้คำศัพท์ที่ดีกว่ากลิ่นรหัส เพียงแค่อ่านหนังสือเกี่ยวกับการปรับโครงสร้างที่ใช้ประมาณหนึ่งพันครั้ง มันเหมือนเล็บบนกระดาน
JeffO

1
@Jeff O: ใช่ฉันพบว่าคนที่ดูเหมือนจะขว้างคำนั้นโดยทั่วไปไม่ค่อยมีประสบการณ์มากนัก
Ed S.

6
@Jeff O และ @Ed S: IME "code ดม" เป็นคำที่คนทั่วไปใช้เมื่อพวกเขาหมายถึง "ฉันไม่ชอบ แต่ฉันไม่มีเหตุผล"
Steven Evers

3
@SnOrfus: อ๋อหรือเมื่อพวกเขามีมุมมอง "ทางศาสนา" ที่มักจะไม่ค่อยเข้าใจในทางปฏิบัติเช่น"วิธีการไม่ควรมีมากกว่า X จำนวนบรรทัด"ซึ่งโดยปกติแล้วจะเป็นเพียงการทำซ้ำสิ่งที่พวกเขาอ่านที่ไหนสักแห่ง
Ed S.

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

10

หลักฐานของคุณผิด

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

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


6

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

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

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


6

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

เมื่อคุณใช้ไวยากรณ์ของคุณสมบัติ C # คอมไพเลอร์จะสร้างเมธอด getter และ setter อย่างเงียบ ๆ ด้วยเมทาดาทาที่บอกภาษาที่เข้าใจคุณสมบัติว่าเป็นคุณสมบัติการสร้างประโยคระดับเฟิร์สคลาสเพื่อปฏิบัติต่อพวกมัน นั่นคือความจริงแล้วน้ำตาล syntactic ที่คุณต้องการ บางภาษาที่สามารถทำงานบน CLR ไม่ได้ซ่อนรายละเอียดนี้จากคุณ (Boo ถ้าหน่วยความจำทำหน้าที่ฉันและการใช้งาน Lisp บางอย่าง) และคุณสามารถโทรหา getters และ setters อย่างชัดเจน

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

ตอนนี้คำถามที่กว้างขึ้นก็คือว่าวิธีการทะเยอทะยานและ Setter เป็นจริงสิ่งที่ดี มีการแลกเปลี่ยนกันอย่างชัดเจน ถ้าคุณมีวิธีการเปลี่ยนแปลงรหัสของคุณคือขนานน้อยโดยเนื้อแท้เพราะตอนนี้คุณต้องจัดการกับปัญหาการประสานด้าย และเป็นไปได้มากที่คุณจะเสี่ยงต่อการฝ่าฝืนกฎหมายของ Demeter โดยใช้วิธีการเปลี่ยนแปลง (ไม่ว่าจะเรียกว่าคุณสมบัติหรือวิธี getter / setter พวกมันเทียบเท่ากัน) เพราะมันสะดวกที่จะทำเช่นนั้น

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

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

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

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


5

อีกเหตุผลที่สำคัญในหนังสือของฉันสำหรับการใช้คุณสมบัติคือพวกเขาสามารถเพิ่มการอ่านได้อย่างมาก

account.setBalance(Account.getBalance()+deposit);

ชัดแจ้งน้อยกว่ามาก

account.Balance += deposit;

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

9
ทำไมไม่บัญชีฝากเงิน (จำนวน)?
xofz

4
@Sam Pearson: +1 ตัวอย่างที่สมบูรณ์แบบของเหตุที่ getters / setters มักแสดงถึงการออกแบบที่ไม่ดี
Nemanja Trifunovic

4

คุณมีมุมมองทางศาสนาที่ตรงกันข้ามกับฉัน :)

เมื่อฉันย้ายจาก Delphi ไปยัง Java การขาดคุณสมบัติก็ดูถูกฉันอย่างมาก ฉันเคยประกาศคุณสมบัติและชี้ไปที่ตัวแปรส่วนตัวโดยตรงหรือเขียน getter (ที่ได้รับการป้องกัน) และ setter แล้ว "ประปา" พวกเขาไปยังสถานที่ให้บริการ สิ่งนี้ห่อหุ้มคุณสมบัติและควบคุมว่าควรเข้าถึงในลักษณะที่ชัดเจนได้อย่างไร คุณสามารถมีคุณสมบัติแบบอ่านอย่างเดียวซึ่งคำนวณผลรวมเมื่อเข้าถึงและเรียกว่า "รวม" ไม่ใช่ "_getTotal ()" หรือ ballochs ที่คล้ายกัน นอกจากนี้ยังหมายความว่าคุณสามารถ จำกัด การเข้าถึงคุณสมบัติได้ด้วยการทำให้พวกเขาได้รับการปกป้องในคลาสฐานนามธรรมจากนั้นย้ายพวกเขาไปสู่สาธารณะหรือเผยแพร่ในคลาสย่อย

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


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

Delphi ใช้คุณสมบัติคลื่นไส้ในทางที่ผิด คุณไม่เรียงลำดับรายการคุณตั้งค่าของคุณสมบัติการsorted trueดังนั้นการตั้งค่าfalseให้รายการเดิม : D หรือสับแบบสุ่มหรือไม่ : D หรืออะไรก็ตามมันแค่โง่ นอกจากนี้มันช้ามากเมื่อเทียบกับชุดเรียงที่เหมาะสม คุณสมบัติไม่เลว แต่ฉันได้เรียนรู้ที่จะใช้มันอย่างประหยัด (จนถึงจุดที่มีความสุขมากกับผู้บุกรุกและผู้ตั้งค่าฉันใช้ Java เป็นส่วนใหญ่)
maaartinus

1

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

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

ทุกวันนี้มีหลายกรณีที่คุณสมบัติการเข้าถึงและแก้ไขไม่ผ่านรหัสปกติ - เช่นขณะทำการดีบัก


1

อีกมุมหนึ่ง - พวกมันมาจาก VB จริงๆ โปรดจำไว้ว่าย้อนกลับไปในยุคมืดมนของศตวรรษที่ 20 เมื่อ. NET รู้สึกถึงความสำคัญอย่างหนึ่งคือมันง่ายสำหรับการแทนที่ VB เพื่อให้โปรแกรมเมอร์ VB ของคุณสามารถลากและวางสิ่งต่างๆลงบนเว็บฟอร์มได้ VB มีคุณสมบัติดังนั้นคุณจำเป็นต้องเก็บคุณสมบัตินั้นไว้เพื่อแปลสิ่งที่ถูกต้อง


1
Anders Heljsberg ออกแบบ C # (และ IL บางตัว) และออกแบบ Delphi - ซึ่งมีคุณสมบัติ
Jesse C. Slicer

1

มีวัตถุประสงค์อย่างน้อยสองประการสำหรับคุณสมบัติ:

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

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


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

1
การเปลี่ยนเขตข้อมูลสาธารณะเป็นคุณสมบัติจะทำลายความเข้ากันได้ของไบนารีรหัสการบริโภคจะต้องมีการคอมไพล์ใหม่ - แม้ว่าจะไม่ได้รับการแก้ไขซึ่งฉันเดาว่าเป็นสิ่งที่คุณได้รับ :)
MattDavey

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