ฉันไม่สามารถใช้วิธีการคงที่ทั้งหมดได้หรือไม่


64

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

public class Subject
{
    public int Id {get; set;}
    public string Name { get; set; }

    public static bool UpdateSubject(Subject subject)
    {
        //Do something and return result
        return true;
    }
    public bool UpdateSubject()
    {
        //Do something on 'this' and return result
        return true;
    }
}

ฉันรู้ว่าฉันจะได้รับความบันเทิงมากมายจากชุมชนสำหรับคำถามที่น่ารำคาญนี้ แต่ฉันไม่สามารถหยุดถามตัวเองได้

สิ่งนี้ไม่สามารถใช้ได้เมื่อจัดการกับมรดกหรือไม่?

Update:
มันเกิดขึ้นที่สถานที่ทำงานของเราตอนนี้ เรากำลังพัฒนาแอพพลิเคชั่นเว็บ asp.net 6 เดือนกับนักพัฒนา 5 คน สถาปนิกของเราตัดสินใจว่าเราใช้วิธีการคงที่ทั้งหมดสำหรับ API ทั้งหมด เหตุผลของเขาคือวิธีการแบบคงที่มีน้ำหนักเบาและเป็นประโยชน์ต่อเว็บแอปพลิเคชัน


9
Rich Hickey จะกระตุ้นให้บางสิ่งบางอย่างที่ไม่มีลักษณะเช่นนั้น (ทุกวิธีคงที่) ถ้าคุณชอบสไตล์การใช้งานคุณอาจใช้ภาษาที่ใช้งานได้ดี) ไม่ใช่ทุกสิ่งในซอฟต์แวร์ที่เป็นแบบอย่างที่ดีที่สุด
งาน

13
@ งาน: ฉันไม่เห็นจริงๆว่ามันทำงานอย่างไร - มันเป็นขั้นตอน
Aaronaught

2
@Job: ชั้นนี้ไม่เปลี่ยนรูป
Aaronaught

3
@ DonalFellows: แน่นอนคุณสามารถ C # และ F # เป็นทั้งกระบวนทัศน์แบบผสม แต่ความจริงก็ยังคงอยู่วิธีการแบบคงที่! = การเขียนโปรแกรมการทำงาน FP หมายถึงฟังก์ชั่นการผ่าน / การผูกมัดประเภทข้อมูลที่ไม่เปลี่ยนรูปการหลีกเลี่ยงผลข้างเคียง ฯลฯ ซึ่งตรงกันข้ามกับสิ่งที่โค้ดขนาดสั้นใน OP ทำ
Aaronaught

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

คำตอบ:


87

ฉันจะไปกับปัญหาที่ชัดเจนที่สุดของวิธีการคงที่กับพารามิเตอร์ "นี้" ชัดเจน:

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

  2. เรียงลำดับของส่วนขยายของ # 1 คุณไม่สามารถแทนที่อินสแตนซ์ของคลาสด้วยอินเทอร์เฟซเนื่องจากอินเทอร์เฟซ (ในภาษาส่วนใหญ่) ไม่สามารถประกาศstaticวิธีการ

  3. การใช้คำฟุ่มเฟื่อยที่ไม่จำเป็น ข้อไหนอ่านได้มากกว่าSubject.Update(subject)หรือเพียงsubject.Update()?

  4. ตรวจสอบข้อโต้แย้ง อีกครั้งขึ้นอยู่กับภาษา แต่หลายคนจะรวบรวมการตรวจสอบโดยนัยเพื่อให้แน่ใจว่าthisอาร์กิวเมนต์ไม่ได้nullเพื่อป้องกันข้อผิดพลาดการอ้างอิงที่เป็นโมฆะจากการสร้างเงื่อนไขรันไทม์ที่ไม่ปลอดภัย (ชนิดของบัฟเฟอร์ที่โอเวอร์รัน) ไม่ได้ใช้วิธีการแบบอินสแตนซ์คุณจะต้องเพิ่มการตรวจสอบนี้อย่างชัดเจนในตอนต้นของทุกวิธี

  5. มันทำให้สับสน เมื่อโปรแกรมเมอร์ธรรมดาที่สมเหตุสมผลเห็นstaticวิธีการเขามักจะคิดว่ามันไม่จำเป็นต้องมีอินสแตนซ์ที่ถูกต้อง (เว้นแต่จะใช้หลายอินสแตนซ์เช่นวิธีการเปรียบเทียบหรือความเท่าเทียมกันหรือคาดว่าจะสามารถทำงานกับnullการอ้างอิงได้) . การเห็นวิธีการคงที่ที่ใช้วิธีนี้จะทำให้เราทำสองหรือสามใช้และหลังจากครั้งที่ 4 หรือ 5 เราจะเครียดและโกรธและพระเจ้าช่วยคุณถ้าเรารู้ที่อยู่บ้านของคุณ

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

มันยากที่จะเข้าใจเหตุผลที่ดีที่จะแทนที่วิธีการเช่นด้วยวิธีการคงที่ โปรดอย่า


5
+1 สำหรับบรรทัดสุดท้ายของคุณเพียงอย่างเดียว ฉันหวังว่าผู้คนจำนวนมากจะคิดว่า "วิธีการแบบอินสแตนซ์" ก่อนที่พวกเขาจะคิดว่า "วิธีแบบคงที่"
Stuart Leyland-Cole

4
+1 ฉันจะเพิ่มวิธีการคงที่ทำให้ยากต่อการเขียนการทดสอบในกรณีส่วนใหญ่คุณไม่สามารถเยาะเย้ยพวกเขา: เมื่อส่วนใดส่วนหนึ่งของรหัสของคุณขึ้นอยู่กับวิธีการคงที่คุณไม่สามารถแทนที่ด้วย - op ในการทดสอบของคุณ ตัวอย่างที่สำคัญในโลก .NET จะเรียนเหมือนFile, FileInfoและDirectoryInfo(และในความเป็นจริงมีห้องสมุดที่ซ่อนอยู่เบื้องหลังพวกเขาการเชื่อมต่อนั้นจะสามารถฉีดตามความจำเป็นและเย้ยหยันออกมาในการทดสอบ)
sm

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

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

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

13

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


FWIW ด้วย C คุณสามารถทำการจัดส่งเสมือนเช่นนี้obj->type->mthd(obj, ...);และนั่นก็คล้าย ๆ กับสิ่งที่เกิดขึ้นกับการจัดส่งเสมือนจริงในภาษาอื่น ๆ (แต่อยู่เบื้องหลัง)
Donal Fellows

@Karl คุณช่วยให้การอ้างอิงเป็นลายลักษณ์อักษรเพื่อเริ่มขุดลึกลงไปได้ไหม?
Jorge Lavín

คุณอาจต้องการดูGObjectเป็นการดำเนินการอ้างอิงที่ดี
Karl Bielefeldt

10

ปัญหาเกี่ยวกับวิธีการคงที่มาทันทีที่คุณต้องการชั้นย่อย

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


2
นี้ไม่จำเป็นต้องมีปัญหา บางภาษามีกลไกอื่น ๆ (ไม่ใช่วิธีเสมือนใน C ++ และ C #) สำหรับการทำสิ่งเดียวกันโดยเจตนา - C # ยังมีวิธี "แบบปิดผนึก" เพื่อขยายแนวคิดนี้ต่อไป! เห็นได้ชัดว่าคุณจะไม่ทำเช่นนี้เพียงเพื่อความหายนะของมัน แต่มันเป็นเทคนิคที่ดีที่จะต้องตระหนักถึง ...
Shog9

@Steve ซึ่งไม่ได้แทนที่เนื่องจากคุณยังสามารถเรียกทั้งสองวิธีได้โดยตรง

@Steve ในวิธีการคงที่ของ Java ไม่สามารถเขียนทับได้

@ Thorbjørn - คำถามแรกไม่ได้ติดแท็ก Java หรือภาษา OOP เฉพาะอื่น ๆ ที่สำคัญกว่านั้นฉันไม่ได้บอกว่าคุณสามารถแทนที่ฟังก์ชันสมาชิกแบบคงที่ได้ ฉันพยายามใช้การเปรียบเทียบเพื่อหาจุด เมื่อฉันล้มเหลวอย่างชัดเจนความคิดเห็นที่ถูกลบ
Steve314

2
ในแง่หนึ่งสิ่งเหล่านี้ยังคงเป็น "วิธีการใช้งานใหม่" ไม่เพียงอยู่ในความหมาย OOP มาตรฐาน สิ่งนี้ให้ความรู้สึกเหมือนฉันกำลังพูดว่า "ถ้อยคำของคุณไม่สมบูรณ์แบบเช่นกันนูร์ - นา - นู - นูร์ - นูร์" ;-)
Steve314

7

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

ใส่อีกวิธีหนึ่งstaticคำสำคัญทำให้การประกาศเป็นส่วนหนึ่งของคำจำกัดความของคลาสดังนั้นจึงกลายเป็นจุดอ้างอิงเดียวในทุกอินสแตนซ์ของคลาส (วัตถุถูกทำให้เป็นอินสแตนซ์จากคลาส)

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

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


1
ฉันเข้าใจว่า OP staticหมายถึงอะไรเขาถามว่าทำไมไม่เพียง แต่ประกาศว่าทุกอย่างเป็นแบบคงที่
Ed S.

1
เขากำลังผ่านตัวอย่างSubject- แต่เป็นพารามิเตอร์ที่ชัดเจนแทนที่จะเป็นthisพารามิเตอร์โดยนัย
Steve314

ใช่ ... แต่ฉันไม่เห็นประเด็นของคุณฉันคิดว่า
Ed S.

@Ed - มีเพียงคุณเท่านั้นที่สามารถทำสิ่งต่างๆได้โดยใช้พารามิเตอร์ที่ชัดเจนซึ่งคุณสามารถทำได้ผ่านthisพารามิเตอร์ทางอ้อม มีความแตกต่างในความคาดหวัง แต่นอกเหนือจากการสืบทอดไม่มีความแตกต่างที่แท้จริงในสิ่งที่คุณสามารถทำได้ ตัวอย่างเช่นสมาชิกที่ไม่คงที่สามารถเข้าถึงได้ - ผ่านพารามิเตอร์ที่ชัดเจน
Steve314

ฉันทำงานภายใต้ข้อสมมติที่ว่าคุณไม่สามารถหาสมาชิกส่วนตัวของการโต้แย้งใน C # ได้แม้ว่าจะใช้วิธีการแบบคงที่ที่ประกาศในคลาสเดียวกัน ไม่แน่ใจว่าทำไมฉันจึงคิดอย่างนั้น แต่ฉันผิด
Ed S.

3

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

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

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


1
คำพูดของคุณ "... เป็นการย้อนกลับไปสู่ขั้นตอนการเขียนโปรแกรม ... " ทำให้ฉันคิดว่าคุณคิดว่ามันแย่มากฉันคิดว่ามันเป็นส่วนหนึ่งของ OO ในแง่หนึ่ง
NoChance

making ... unit testing much easier.ไม่มันจะไม่ มันทำให้มันเป็นรหัสใด ๆ ที่เรียกวิธีการคงที่เป็นไปไม่ได้ที่จะทดสอบหน่วยเนื่องจากคุณไม่สามารถแยกได้จากวิธีการคงที่ การเรียกใช้เมธอดแบบสแตติกกลายเป็นการพึ่งพาฮาร์ดโค้ดไปยังคลาสนั้น
StuperUser

2

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

เนื่องจากไวยากรณ์ตัวอย่างของคุณแนะนำ Java หรือ C # ฉันคิดว่าThorbjørn Ravn Andersen มีสิทธิ์ที่จะชี้ให้เห็นถึงปัญหาการแทนที่ ด้วยวิธีการคงที่ไม่มีพารามิเตอร์ "พิเศษ" สำหรับการรวมล่าช้าที่จะขึ้นอยู่กับดังนั้นคุณไม่สามารถมีผลผูกพันล่าช้า

ผลวิธีสแตติกเป็นเพียงฟังก์ชั่นในโมดูลโมดูลนั้นมีชื่อเดียวกันกับคลาสซึ่งไม่ใช่วิธี OOP เลย


2

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

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


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

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

@kai ตามที่ฉันพูดไปมาก คลาส Math เป็นข้อยกเว้นที่สมเหตุสมผลแม้ว่าการแนบไปกับชนิดตัวเลขจะไม่เป็นความคิดที่ไม่ดี
Loren Pechtel

2

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

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

(เน้นตัวหนาเป็นของฉัน)

2c ของฉันในส่วนนี้ของคำถามคือ:

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

บทละครผู้สนับสนุนของมารน้อยเกี่ยวกับเรื่องนี้: เราสามารถไปไกลกว่านี้และพูดสิ่งต่าง ๆ เช่น:

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

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

ในความเป็นจริง IMHO ประเด็นข้างต้น (และวิธีการทั่วไปของ "ลองใช้สถิติเพราะเร็วกว่า") คือการโต้แย้ง / การประเมินฟางคน:

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

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


2

นี่เป็นคำถามที่น่าสนใจมากที่มีคำตอบแตกต่างกันมากขึ้นอยู่กับชุมชนที่คุณถาม คำตอบอื่น ๆ น่าจะเป็น C # หรือ java bias: ภาษาการเขียนโปรแกรมซึ่งส่วนใหญ่เป็นวัตถุบริสุทธิ์และมีมุมมองที่เป็นสำนวนเกี่ยวกับการวางแนววัตถุ

ในชุมชนอื่นเช่น C ++ การวางแนววัตถุจะตีความด้วยความมีอิสระมากขึ้น บางคนรู้ดีว่าผู้เชี่ยวชาญได้ศึกษาเรื่องนี้แล้วและที่จริงแล้วสรุปได้ว่าฟังก์ชั่นฟรีปรับปรุงการห่อหุ้ม (การเน้นเป็นของฉัน):

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

สก็อตต์เมเยอร์ส

สำหรับผู้ที่ไม่คุ้นเคยกับคำศัพท์ C ++:

  • ฟังก์ชั่นสมาชิก = วิธีการ
  • ฟังก์ชั่นที่ไม่ใช่สมาชิก = วิธีคงที่
  • ไม่ใช่เพื่อน = ใช้ API สาธารณะเท่านั้น
  • ฟังก์ชั่นที่ไม่ใช่สมาชิกที่ไม่ใช่เพื่อน = วิธีคงที่ที่ใช้ API สาธารณะเท่านั้น

ตอนนี้เพื่อตอบคำถามคุณ:

ฉันไม่สามารถใช้วิธีการคงที่ทั้งหมดได้หรือไม่

ไม่คุณไม่ควรใช้วิธีการคงที่เสมอไป

แต่คุณควรใช้เมื่อใดก็ตามที่คุณจำเป็นต้องใช้API สาธารณะของชั้นเรียนเท่านั้น


-3

ใน Java ...

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

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

ควรใช้รหัสคงที่สำหรับคลาสเฉพาะ คงที่ไม่ทำงานกับมรดก

ตัวอย่างที่ดีของการใช้วิธีการคงที่คือฟังก์ชั่นอิสระโดยไม่มีผลข้างเคียง

ดูคำหลักที่ซิงโครไนซ์ด้วย ...


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