แนวคิดของคลาสเปลี่ยนไปอย่างไรเมื่อส่งข้อมูลไปยังตัวสร้างแทนพารามิเตอร์เมธอด?


12

สมมติว่าเรากำลังแยกวิเคราะห์ การใช้งานอย่างหนึ่งอาจ:

public sealed class Parser1
{
    public string Parse(string text)
    {
       ...
    }
}

หรือเราสามารถส่งข้อความไปยังผู้สร้างได้:

public sealed class Parser2
{
    public Parser2(string text)
    {
       this.text = text;
    }

    public string Parse()
    {
       ...
    }
}

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

คำถามอื่นเกิดขึ้นเมื่อฉันตระหนักว่าอินเทอร์เฟซจะค่อนข้างไม่มีความหมายในการใช้งานที่สอง:

public interface IParser
{
    string Parse();
}

... ซึ่งอินเทอร์เฟซสำหรับอินเทอร์เฟซแรกสามารถตอบสนองวัตถุประสงค์บางอย่างได้อย่างน้อย นั่นหมายถึงสิ่งใดเป็นพิเศษหรือไม่ว่าคลาสนั้นเป็น "อินเตอร์เฟส" หรือไม่?


นี่เป็นครั้งแรกที่ฉันได้เห็น Q & A ที่เป็นประโยชน์เกี่ยวกับความหมายของ OO ที่แสดงออกถึงเจตนา ถึงตอนนี้มันก็แค่น้ำตาลซินแทกติกกับฉัน

คำตอบ:


11

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

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

เกี่ยวกับตัวอย่างที่สองของคุณ:

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

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

8

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

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

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


+1 การทำงานร่วมกันเป็นวิธีที่ฉันตัดสินใจว่ามันเป็นของวิธีการหรือตัวสร้าง
jhewlett

4

การใช้งานง่ายในทั้งสองกรณี แต่การเปิดใช้งานการป้อนพารามิเตอร์กับ Parser1 หมายความว่าอย่างไรเมื่อเปรียบเทียบกับอีกกรณีหนึ่ง

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

แนวคิดของคลาสเปลี่ยนไปอย่างไรเมื่อส่งข้อมูลไปยังตัวสร้างแทนพารามิเตอร์เมธอด?

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

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

คำถามอื่นเกิดขึ้นเมื่อฉันตระหนักว่าอินเทอร์เฟซจะค่อนข้างไม่มีความหมายในการใช้งานที่สอง:

อินเตอร์เฟสเช่นเดียวกับใน API เป็นวิธีการและคุณสมบัติที่เปิดเผยรหัสลูกค้า อย่าห่อหุ้มด้วยผ้าpublic interface { ... }เท่านั้น ดังนั้นความหมายของอินเทอร์เฟซจึงอยู่ใน - หรือคอนสตรัคเตอร์ vs เมธอดพารามิเตอร์ขึ้นเขียงไม่ใช่public interface Iparservspublic sealed class Parser

sealedระดับเป็นเลขคี่ ถ้าฉันกำลังคิดเกี่ยวกับการใช้งาน parser ที่แตกต่างกัน - คุณพูดถึง "Iparser" - แล้วมรดกเป็นความคิดแรกของฉัน มันเป็นเพียงส่วนขยายแนวคิดตามธรรมชาติในความคิดของฉัน IE ทั้งหมดParserXs เป็นพื้นฐานParsers จะพูดยังไงดี ... เยอรมันเชพพาร์ดเป็นสุนัข (มรดก) แต่ฉันสามารถฝึกนกแก้วให้เห่า (ทำตัวเหมือนสุนัข - "อินเทอร์เฟซ"); แต่พอลลี่ไม่ได้เป็นสุนัขเพียงแค่แกล้งทำเป็นเรียนรู้บางส่วนของความดื้อรั้น เรียนนามธรรมหรือมิฉะนั้นให้บริการอย่างสมบูรณ์แบบเดียวกับอินเตอร์เฟซ


ถ้ามันเดินเหมือนตัวแยกวิเคราะห์และพูดเหมือนตัวแยกวิเคราะห์ก็คือ ... เป็ด!

2

รุ่นที่สองของชั้นสามารถทำให้ไม่เปลี่ยนรูป

ยังคงสามารถใช้อินเทอร์เฟซเพื่อให้ความสามารถในการสลับการใช้งานพื้นฐาน


มันไม่สามารถทำให้ไม่เปลี่ยนรูปแบบในเวอร์ชั่นแรกด้วยการส่งข้อมูลไปยังชั้นเรียนด้วยวิธีการใช้งานได้หรือไม่?
ciscoheat

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

Scylla และ Charybdis: ฉันจะเลือก OO หรือข้อมูลที่ไม่เปลี่ยนรูปแบบหรือไม่? ฉันไม่เคยได้ยินมาก่อนเลย

2

Parser1

การสร้างด้วยคอนสตรัคเตอร์เริ่มต้นและการส่งผ่านข้อความอินพุตไปยังเมธอดหมายความว่า Parser1 สามารถใช้งานได้อีกครั้ง

Parser2

การส่งข้อความอินพุตเข้าสู่ Constructor หมายความว่าต้องสร้าง Parser2 ใหม่สำหรับแต่ละอินพุตสตริง


แน่นอนว่าถ้าเรายกระดับไปอีกระดับจะสรุปได้อย่างไรเกี่ยวกับวัตถุที่สามารถนำกลับมาใช้ใหม่ได้เมื่อเทียบกับวัตถุที่ไม่สามารถนำกลับมาใช้ใหม่ได้?
ciscoheat

ฉันจะไม่คิดอะไรมากไปกว่านั้นแทนที่จะใช้เอกสารแทน
Mike Partridge

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