ไม่มีวัตถุพฤติกรรมใน OOP - ขึ้นเขียงการออกแบบของฉัน


94

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

จนถึงตอนนี้ดีมาก

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

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

สมมติว่าคุณมี API เกมการ์ดทั่วไป Cardคุณได้เรียน ตอนนี้Cardคลาสนี้จำเป็นต้องกำหนดทัศนวิสัยให้กับผู้เล่น

วิธีหนึ่งคือการมีboolean isVisible(Player p)ในCardชั้นเรียน

อีกอย่างคือให้มีboolean isVisible(Card c)ในPlayerชั้นเรียน

ฉันไม่ชอบวิธีแรกโดยเฉพาะอย่างยิ่งในขณะที่มันมอบความรู้เกี่ยวกับระดับที่สูงกว่าPlayerระดับให้อยู่ในระดับที่ต่ำกว่าCardระดับ

แต่ฉันเลือกใช้ตัวเลือกที่สามที่เรามีViewportคลาสซึ่งให้ a Playerและรายการการ์ดกำหนดว่าจะมองเห็นการ์ดใด

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

ชัดเจนว่าเป็นแนวคิดหลักของ OOP

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

PS นี่เป็นอีกตัวอย่าง:

สมมติว่าคุณมีคลาสDocumentIdที่ไม่เปลี่ยนรูปแบบมีเพียงBigDecimal idสมาชิกเดียวและทะเยอทะยานสำหรับสมาชิกนี้ ตอนนี้คุณต้องมีวิธีการบางอย่างซึ่งได้รับDocumentIdผลตอบแทนDocumentสำหรับรหัสนี้จากฐานข้อมูล

คุณ:

  • เพิ่มDocument getDocument(SqlSession)วิธีการในDocumentIdชั้นเรียนทันทีแนะนำความรู้เกี่ยวกับการคงอยู่ของคุณ ( "we're using a database and this query is used to retrieve document by id"), API ที่ใช้ในการเข้าถึงฐานข้อมูลและสิ่งที่คล้ายกัน นอกจากนี้คลาสนี้ยังต้องการไฟล์ JAR ที่มีอยู่เพื่อคอมไพล์
  • เพิ่มคลาสอื่น ๆ ด้วยวิธีการDocument getDocument(DocumentId id)ปล่อยให้DocumentIdคลาสเป็นตายไม่มีพฤติกรรมคลาสที่มีโครงสร้างเหมือนกัน

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

31
"สิ่งนี้ชัดเจนต่อแนวคิดหลักของ OOP" - ไม่มันไม่ใช่ แต่เป็นความเข้าใจผิด
Doc Brown

5
ฉันเดาว่าปัญหานี้เกิดขึ้นในความจริงที่ว่ามีโรงเรียนหลายแห่งสำหรับ "การวางแนววัตถุ" ในอดีต - วิธีที่ผู้คนอย่าง Alan Kay ให้ความหมาย (ดูgeekswithblogs.net/theArchitectsNapkin/archive/2013/09/08/) … ) และวิธีการสอนในบริบทของ OOA / OOD โดยคนเหล่านั้นจาก Rational ( en.wikipedia.org/wiki/Object-oriented_analysis_and_design )
Doc Brown

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

5
ใครบอกว่าคลาส beheaviourless นั้นต่อต้านรูปแบบ?
James Anderson

คำตอบ:


42

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

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

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

แต่มันเป็นหน้าที่ของการที่Cardจะรู้ว่าPlayerมันคืออะไร?

และใช้เหตุผลCard.isVisibleTo(Player p)แต่ไม่Player.isVisibleTo(Card c)? หรือในทางกลับกัน?

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

เมื่อเวลาผ่านไปมันจะนำไปสู่การประนีประนอมการออกแบบเน่าเสียของการดำเนินการisVisibleToเกี่ยวกับทั้งสอง CardและPlayerชั้นซึ่งผมเชื่อว่าไม่มีไม่มี ทำไมเป็นเช่นนั้น เพราะผมแล้วคิดวันที่น่าอับอายเมื่อplayer1.isVisibleTo(card1)จะกลับค่าที่แตกต่างกว่าที่card1.isVisibleTo(player1).ผมคิดว่า - มันอัตนัย - นี้ควรจะทำไปไม่ได้โดยการออกแบบ

การแสดงผลรวมของบัตรและผู้เล่นที่ดีกว่าควรถูกควบคุมโดยการเรียงลำดับของวัตถุบริบทบางอย่าง - ไม่ว่าจะเป็นViewport, หรือDealGame

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

ฉันยังคงอาจจะใช้isVisibleToในCardแต่ผ่านวัตถุบริบทให้มันและทำให้Cardผู้ร่วมประชุมแบบสอบถาม โปรแกรมเชื่อมต่อเพื่อหลีกเลี่ยงการมีเพศสัมพันธ์สูง

สำหรับตัวอย่างที่สองของคุณ - ถ้า ID เอกสารประกอบด้วยเพียง a BigDecimalทำไมสร้างคลาส wrapper สำหรับมันเลย?

ฉันจะบอกว่าสิ่งที่คุณต้องการคือ DocumentRepository.getDocument(BigDecimal documentID);

โดยวิธีการในขณะที่ขาดจาก Java มีstructs ใน C #

ดู

สำหรับการอ้างอิง มันเป็นภาษาเชิงวัตถุ แต่ไม่มีใครทำเรื่องใหญ่ได้


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

3
@ Aschratt: โครงสร้างไม่รองรับการสืบทอด โครงสร้างสามารถใช้อินเทอร์เฟซ แต่โครงสร้างที่ใช้อินเทอร์เฟซทำงานแตกต่างจากวัตถุคลาสที่ทำเช่นเดียวกัน ในขณะที่เป็นไปได้ที่จะทำให้ structs ทำงานเหมือนวัตถุ แต่กรณีที่ดีที่สุดสำหรับ structs ก็คือเมื่อเราต้องการบางสิ่งที่ทำตัวเหมือนโครงสร้าง C และสิ่งที่หนึ่งคือ encapsulating นั้นเป็นแบบดั้งเดิมหรือคลาสอื่นที่ไม่เปลี่ยนรูป
supercat

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

@supercat นี่เป็นคำถามที่แยกต่างหากหรือเซสชันการแชท แต่ตอนนี้ฉันไม่สนใจ :-( คุณพูดว่า (ใน C #) "โครงสร้างที่ใช้ส่วนต่อประสานต่างจากพฤติกรรมของคลาสวัตถุที่ทำเช่นเดียวกัน" ฉันยอมรับว่า มีความแตกต่างของพฤติกรรมอื่น ๆ ที่ต้องพิจารณา แต่ AFAIK ในโค้ดต่อไปนี้Interface iObj = (Interface)obj;พฤติกรรมของiObjไม่ได้รับผลกระทบจากstructหรือclassสถานะของobj(ยกเว้นว่ามันจะเป็นสำเนาที่บรรจุอยู่ในกล่องที่ได้รับมอบหมายถ้ามันเป็นstruct)
Mark Hurd

150

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

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

สมมติว่าคุณมี API เกมการ์ดทั่วไป คุณมีคลาสการ์ด ตอนนี้คลาสการ์ดนี้จำเป็นต้องกำหนดทัศนวิสัยให้กับผู้เล่น

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

วิธีหนึ่งคือการมีบูลีน isVisible (Player p) ในคลาสการ์ด อีกอย่างคือการมีบูลีน isVisible (การ์ด c) ในคลาสผู้เล่น

ทั้งคู่น่ากลัว อย่าทำอย่างใดอย่างหนึ่ง ทั้งผู้เล่นและการ์ดไม่รับผิดชอบต่อการนำกฎของบริดจ์ไปใช้!

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

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

อย่างไรก็ตามวิธีการนี้ใช้ทั้งคลาส Card และ Player ของฟังก์ชันสมาชิกที่เป็นไปได้

ดี!

เมื่อคุณทำสิ่งอื่นนอกเหนือจากการมองเห็นการ์ดแล้วคุณจะเหลือคลาส Card และ Player ซึ่งมีข้อมูลล้วนๆเนื่องจากมีการใช้งานฟังก์ชันทั้งหมดในคลาสอื่น ๆ ซึ่งส่วนใหญ่เป็นคลาสที่ไม่มีข้อมูลวิธีการเช่น Viewport ด้านบน ชัดเจนว่าเป็นแนวคิดหลักของ OOP

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

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

นี่คือวิธีที่ฉันจะออกแบบระบบของคุณ

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

ถัดไปลักษณะของผู้เล่นคืออะไร? ผู้เล่นกินลำดับของการกระทำที่มองเห็นและผลิตกระทำ

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

  • ผู้เล่นคนที่สิบหัวใจถูกส่งมาให้คุณโดยผู้เล่นที่สาม
  • ผู้เล่นสองการ์ดได้ถูกมอบให้กับผู้เล่นหนึ่งคนโดยผู้เล่นที่สาม

จากนั้นขอให้ผู้เล่นดำเนินการ

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

และอื่น ๆ

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


41
@gnat: ความเห็นที่แตกต่างจาก Alan Kay คือ"จริงๆแล้วฉันสร้างคำว่า" เชิงวัตถุ "และฉันสามารถบอกคุณได้ว่าฉันไม่มีภาษา C ++ ในใจ"มีภาษา OO ที่ไม่มีคลาส จาวาสคริปต์อยู่ในใจ
Eric Lippert

19
@gnat: ฉันจะยอมรับว่า JS อย่างที่เป็นอยู่ในวันนี้ไม่ใช่ตัวอย่างที่ดีของภาษา OOP แต่มันแสดงให้เห็นว่าเราสามารถสร้างภาษา OO ได้โดยไม่ต้องเรียน ฉันยอมรับว่าหน่วยพื้นฐานของ OO-ness ในหอไอเฟลและ C ++ ทั้งคู่เป็นชั้นเรียน ที่ฉันไม่เห็นด้วยเป็นความคิดที่ว่าคลาสเป็นไซน์ใฐานะที่ไม่ใช่ของ OO ไม่ใช่ไซน์ใฐานะที่เป็นของ OO เป็นวัตถุที่แค็ปซูพฤติกรรมและการสื่อสารกับแต่ละอื่น ๆ ผ่านทางอินเตอร์เฟซที่สาธารณะที่ดีที่กำหนด
Eric Lippert

16
ฉันเห็นด้วย w / @EricLippert คลาสไม่ได้เป็นพื้นฐานของ OO และไม่สืบทอดสิ่งที่กระแสหลักอาจพูด การห่อหุ้มข้อมูลพฤติกรรมและความรับผิดชอบเป็นสิ่งที่สามารถทำได้ มีภาษาที่ใช้ต้นแบบนอกเหนือจาก Javascript ซึ่งเป็น OO แต่ไม่มีคลาส มันเป็นความผิดพลาดโดยเฉพาะอย่างยิ่งที่จะมุ่งเน้นไปที่การสืบทอดต่อแนวคิดเหล่านี้ ที่กล่าวว่าชั้นเรียนเป็นวิธีที่มีประโยชน์มากในการจัดการห่อหุ้มพฤติกรรม คุณสามารถใช้คลาสเป็นวัตถุ (และในภาษาต้นแบบตรงกันข้าม) ทำให้เส้นพร่ามัว
Schwern

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

5
@ontagist: ให้ฉันอธิบายสิ่งเล็กน้อยแล้ว พิจารณา C. ฉันคิดว่าคุณคงเห็นด้วยว่า C ไม่มีคลาส อย่างไรก็ตามคุณสามารถพูดได้ว่า structs เป็น "คลาส" คุณสามารถสร้างฟิลด์ของประเภทตัวชี้ฟังก์ชันได้คุณสามารถสร้าง vtables คุณสามารถสร้างวิธีที่เรียกว่า "constructors" ที่ตั้งค่า vtables เพื่อให้ structs บางตัว "สืบทอด" จากกันและกัน และอื่น ๆ คุณสามารถเลียนแบบการสืบทอดคลาสตาม C และคุณสามารถเลียนแบบใน JS แต่การทำเช่นนั้นหมายถึงการสร้างบางสิ่งที่เหนือภาษาที่ยังไม่มี
Eric Lippert

29

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

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

ในขณะที่ OOP มีข้อได้เปรียบที่ชัดเจน (โดยเฉพาะการเขียนโปรแกรมตามขั้นตอนธรรมดา) แต่ก็ไร้เดียงสาที่จะพยายาม OOP ที่“ บริสุทธิ์” ปัญหาบางอย่างไม่สามารถแมปได้ดีกับวิธีการเชิงวัตถุและแก้ไขได้ง่ายขึ้นโดยกระบวนทัศน์อื่น ๆ เมื่อพบปัญหาดังกล่าวอย่ายืนหยัดในแนวทางที่ด้อยกว่า

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

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

    static boolean isVisible(Card c, Player p);
    

    และไม่มีอะไรผิดปกติกับCardการไม่มีวิธีการใดนอกเหนือจากrankและsuitaccessors


11
@UMad ใช่นั่นคือประเด็นของฉันและไม่มีอะไรผิดปกติ ใช้กระบวนทัศน์ <del> ภาษา </del> ที่ถูกต้องสำหรับงานในมือ (อย่างไรก็ตามภาษาส่วนใหญ่นอกเหนือจาก Smalltalk นั้นไม่ใช่เชิงวัตถุล้วนๆเช่น Java, C # และ C ++ รองรับการเขียนโปรแกรมที่จำเป็น, มีโครงสร้าง, ขั้นตอน, แบบแยกส่วน, ใช้งานได้และการเขียนโปรแกรมเชิงวัตถุ : เพื่อให้คุณสามารถใช้พวกเขา)
อมร

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

2
@Schwern หากมีสิ่งใดFibonacciเป็นคลาสย่อยของคลาสนามธรรมSequenceลำดับจะถูกใช้โดยชุดตัวเลขใด ๆ และรับผิดชอบในการจัดเก็บเมล็ดพันธุ์รัฐแคชและตัววนซ้ำ
George Reith

2
ผมไม่ได้คาดหวัง“Fibonacci OOP บริสุทธิ์” ให้มีประสิทธิภาพเพื่อให้nerd-ดัดแปลง โปรดหยุดการอภิปรายแบบวงกลมเกี่ยวกับสิ่งนั้นในความคิดเห็นเหล่านี้แม้ว่าจะมีค่าความบันเทิงที่แน่นอน ตอนนี้เราทำสิ่งที่สร้างสรรค์เพื่อการเปลี่ยนแปลงกันเถอะ!
amon

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

19

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

นี่เป็นคำถามที่ยากเพราะมันมีพื้นฐานอยู่บนสถานที่ที่ค่อนข้างผิดปกติ:

  1. แนวคิดที่ว่า OOP เป็นวิธีการเขียนโค้ดที่ถูกต้องเท่านั้น
  2. แนวคิดที่ว่า OOP เป็นแนวคิดที่ชัดเจน มันกลายเป็นคำศัพท์ที่ยากที่จะหาคนสองคนที่สามารถเห็นด้วยกับสิ่งที่เกี่ยวกับ OOP
  3. แนวคิดที่ว่า OOP นั้นเกี่ยวกับการรวมข้อมูลและพฤติกรรม
  4. ความคิดที่ว่าทุกสิ่งเป็น / ควรเป็นนามธรรม

ฉันจะไม่แตะต้องข้อ # 1-3 มากนักเพราะแต่ละคนสามารถตอบคำถามของตัวเองได้และมันก็เชิญการอภิปรายตามความคิดเห็นมากมาย แต่ฉันพบว่าความคิดของ "OOP เป็นเรื่องเกี่ยวกับการมีเพศสัมพันธ์ข้อมูลและพฤติกรรม" ที่จะหนักใจโดยเฉพาะอย่างยิ่ง ไม่เพียง แต่นำไปสู่ข้อที่ 4 เท่านั้น แต่ยังนำไปสู่แนวคิดที่ว่าทุกอย่างควรเป็นวิธีการ

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

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

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

เป็นไปได้มากที่isVisibleควรเป็นฟังก์ชั่นฟรี


1
+1 สำหรับสามัญสำนึกแทนที่จะไร้เหตุผล
rightfold

จากบรรทัดที่ฉันอ่านเรียงความที่คุณเชื่อมโยงจะมีลักษณะเหมือนแบบอ่านที่เป็นของแข็งที่ฉันไม่ได้มีในขณะที่
Arthur Havlicek

@ArthurHavlicek มันยากที่จะติดตามถ้าคุณไม่เข้าใจภาษาที่ใช้ในตัวอย่างโค้ด แต่ฉันคิดว่ามันค่อนข้างส่องสว่าง
Doval

9

เห็นได้ชัดว่าตามหลักการของ OOP วัตถุที่เป็นเพียงข้อมูล (เช่นโครงสร้างของ C) นั้นถือว่าเป็นรูปแบบการต่อต้าน

ไม่พวกเขาไม่ได้ วัตถุ Plain-Old-Data เป็นรูปแบบที่ถูกต้องสมบูรณ์แบบและฉันคาดหวังว่ามันจะอยู่ในโปรแกรมใด ๆ ที่เกี่ยวข้องกับข้อมูลที่ต้องคงอยู่หรือสื่อสารระหว่างส่วนต่าง ๆ ของโปรแกรมของคุณ

ในขณะที่ชั้นข้อมูลของคุณอาจเก็บพักPlayerคลาสเต็มเมื่ออ่านจากPlayersตาราง แต่อาจเป็นเพียงคลังข้อมูลทั่วไปที่ส่งคืน POD ด้วยเขตข้อมูลจากตารางซึ่งส่งผ่านไปยังพื้นที่อื่นของโปรแกรมที่คุณแปลง ผู้เล่น POD เข้าสู่Playerคลาสที่เป็นรูปธรรมของคุณ

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


5
ไม่เห็นด้วยกับสิ่งที่คุณพูด แต่นี่ไม่ได้ตอบคำถามเลย ที่กล่าวว่าฉันตำหนิคำถามมากกว่าคำตอบ
pdr

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

1
Plain-Old-Data objects are a perfectly valid pattern ฉันไม่ได้บอกว่าพวกเขาไม่ใช่ฉันกำลังบอกว่ามันผิดเมื่อพวกเขาเติมครึ่งล่างของแอปพลิเคชันทั้งหมด
RokL

8

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

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

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

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


คำตอบของ Lippert ด้านบนเป็นตัวอย่างที่ดีกว่าของแนวคิดนี้
RibaldEddie

5

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

สิ่งนี้นำไปใช้กับCard- Playerปัญหา: การสร้างสิ่งที่เป็นViewPortนามธรรมทำให้รู้สึกว่าคุณคิดCardและPlayerเป็นห้องสมุดอิสระสองแห่ง (ซึ่งPlayerบางครั้งก็อาจใช้โดยไม่มีCard) อย่างไรก็ตามฉันมีแนวโน้มที่จะคิดการPlayerระงับCardsและควรให้การCollection<Card> getVisibleCards ()เข้าถึงกับพวกเขา โซลูชันทั้งสอง ( ViewPortและของฉัน) ดีกว่าการนำเสนอisVisibleเป็นวิธีการCardหรือPlayerในแง่ของการสร้างความสัมพันธ์ของรหัสที่เข้าใจได้

DocumentIdวิธีการแก้ปัญหานอกชั้นเรียนมากดีมากสำหรับ มีแรงจูงใจเล็กน้อยที่จะทำให้ (โดยทั่วไปจำนวนเต็ม) ขึ้นอยู่กับไลบรารีฐานข้อมูลที่ซับซ้อน


ฉันชอบบล็อกของคุณ
RokL

3

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

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

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

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

  1. ตกลงหรือไม่ที่จะมีตัวยึดข้อมูลอย่างง่าย (คลาส / โครงสร้างฉันไม่สนใจสิ่งที่พวกเขาทำแบบจำลองสำหรับคำถามนี้) ซึ่งไม่ได้มีฟังก์ชั่นมากมายจริง ๆ ?
  2. ถ้าใช่วิธีที่ดีที่สุดหรือดีที่สุดในการสร้างแบบจำลองคืออะไร?
  3. หากไม่มีเราจะรวมส่วนข้อมูลตัวนับนี้เข้ากับคลาส API ที่สูงขึ้นได้อย่างไร (รวมถึงพฤติกรรม)

มุมมองของฉัน:

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


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

@JohnSaunders ฉันเข้าใจภูมิปัญญาของคุณที่นี่และเห็นด้วยกับขอบเขต แต่ก็มีวิธีการทางความคิดที่จำเป็นเพียงแค่ก่อนที่จะแก้ไขปัญหา ท้ายที่สุดคำถามที่นี่ไม่ได้เป็นแบบปลายเปิดอย่างที่ควรจะเป็น ฉันคิดว่ามันเป็นคำถามที่ถูกต้อง OOD นักออกแบบ OO ที่ใบหน้าของ OOP เริ่มต้น คุณเอาอะไร หากการสรุปช่วยเราได้หารือการสร้างตัวอย่างที่คุณเลือก
Harsha

ฉันออกจากโรงเรียนมานานกว่า 35 ปีแล้ว ในโลกแห่งความเป็นจริงฉันพบคุณค่าน้อยมากใน "แนวคิดเชิงแนวคิด" ฉันพบว่าประสบการณ์จะเป็นครูที่ดีกว่าเมเยอร์ในกรณีนี้
John Saunders

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

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

2

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

ฉันขอแนะนำว่ามันอาจจะมีประโยชน์หากมีCardEntityวัตถุที่ห่อหุ้มแง่มุมเหล่านั้นของการ์ดในส่วนประกอบแยกกัน องค์ประกอบหนึ่งจะเกี่ยวข้องกับเครื่องหมายบนการ์ด (เช่น "Diamond King" หรือ "Lava Blast; ผู้เล่นมีโอกาส AC-3 ที่จะหลบหรือไม่เช่นนั้นจะรับความเสียหาย 2D6") หนึ่งอาจเกี่ยวข้องกับลักษณะเฉพาะของรัฐเช่นตำแหน่ง (เช่นอยู่ในสำรับหรือในมือของ Joe หรือบนโต๊ะด้านหน้าของ Larry) บุคคลที่สามอาจเกี่ยวข้องกับการมองเห็น (อาจไม่มีใครเลยบางทีผู้เล่นหนึ่งคน เพื่อให้แน่ใจว่าทุกอย่างถูกซิงค์อยู่เสมอสถานที่ที่การ์ดอาจจะไม่ถูกห่อหุ้มเป็นฟิลด์ธรรมดา แต่เป็นCardSpaceวัตถุ เมื่อต้องการย้ายไพ่ไปยังที่ว่างหนึ่งจะให้การอ้างอิงที่เหมาะสมCardSpaceวัตถุ; มันจะลบตัวเองออกจากพื้นที่เก่าและนำตัวเองไปสู่พื้นที่ใหม่)

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


0

อย่างไรก็ตามวิธีการนี้ใช้ทั้งคลาส Card และ Player ของฟังก์ชันสมาชิกที่เป็นไปได้

และวิธีการที่ไม่ดี / ไม่ดีแนะนำ?

ที่จะใช้การเปรียบเทียบคล้ายกับตัวอย่างบัตรของคุณให้พิจารณาCarเป็นDriverและคุณจำเป็นต้องตรวจสอบว่าสามารถขับรถDriverCar

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

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

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