เมื่อใดควรใช้ตัวแปรอินสแตนซ์ออบเจ็กต์เทียบกับการส่งอาร์กิวเมนต์ไปยังเมธอด


93

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

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


1
หากคุณมีตัวอย่างที่เฉพาะเจาะจงคุณอาจได้รับคำตอบที่เป็นประโยชน์โดยตรงมากขึ้น
brabster

คำตอบ:


55

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

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

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

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

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


คำตอบของฉันคือการเพิ่มคำตอบนี้ให้กับคำตอบ H-Man2 (อายุการใช้งาน) ควรเป็นแอตทริบิวต์สมาชิกถ้าเป็นสถานะถาวรของวัตถุ นั่นคือค่ามีความสมเหตุสมผลโดยตัวมันเองอยู่นอกขอบเขตของเมธอดสแต็กปัจจุบัน
David Rodríguez - น้ำลายไหล

1
ปฏิกิริยาทางเดินอาหารของฉันคือเห็นด้วยกับ David และ H-MAn2 อย่างไรก็ตามฉันกำลังอ่าน "รหัสสะอาด" โดย Robert c Martin และในบทที่ 3 เขา refactors code เพื่อย้ายบางสิ่งจากพารามิเตอร์ method ไปยังตัวแปร member เนื่องจากการมีพารามิเตอร์จำนวนมากนั้นไม่ดี ในเรื่องความสมดุลฉันเดาว่าถ้าชั้นเรียนของคุณมีความรับผิดชอบเพียงอย่างเดียวอายุการใช้งานของวัตถุจะเท่ากับอายุการใช้งานของการคำนวณนั้นดังนั้นคำตอบที่แท้จริงก็คือถ้าคุณต้องถามคำถามนี้ชั้นของคุณใหญ่เกินไปหรือไม่?
Andy

@ DavidRodríguez-dribeas คุณหมายถึงอะไรโดย method stack?
committedandroider

@committedandroider: ถ้าค่านั้นอยู่ได้นานกว่าการเรียกฟังก์ชันปัจจุบัน
David Rodríguez - dribeas

46

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

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


21

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

นี่คือตัวอย่าง:

myCircle = myDrawing.drawCircle(center, radius);

ตอนนี้ให้การถ่ายภาพคลาส myDrawing ใช้ 15 ฟังก์ชันตัวช่วยในการสร้างวัตถุ myCircle และแต่ละฟังก์ชันเหล่านั้นจะต้องมีจุดศูนย์กลางและรัศมี ไม่ควรตั้งค่าเป็นตัวแปรอินสแตนซ์ของคลาส myDrawing เพราะพวกเขาจะไม่ต้องการอีกแล้ว

ในทางกลับกันคลาส myCircle จะต้องจัดเก็บทั้งศูนย์และรัศมีเป็นตัวแปรอินสแตนซ์

myCircle.move(newCenter);
myCircle.resize(newRadius);

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

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

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


คุณสามารถกำหนดการย้ายเพื่อใช้พารามิเตอร์ (oldCenter, newCenter) ได้
obesechicken13

4

IMHO:

หากตัวแปรเป็นส่วนหนึ่งของสถานะของอินสแตนซ์ก็ควรเป็นตัวแปรอินสแตนซ์ - classinstance HAS-A instancevariable

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

หวังว่าจะช่วยได้


3

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

กำหนดตัวแปรแต่ละตัวก่อนที่คุณจะใช้งาน หากตัวแปรสนับสนุนฟังก์ชันของวิธีการเฉพาะให้ใช้ในขอบเขตของวิธีการเท่านั้น

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

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

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


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