ทำไม Math.Sqrt () เป็นฟังก์ชันคงที่


31

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

 // looks wrong to me
 var y = Math.Sqrt(x);
 // looks better to me
 var y = x.Sqrt();

ToString()ชนิดของมูลค่าชัดสามารถมีวิธีการเช่นเดียวกับในหลายภาษามีวิธีการเช่น

เพื่อตอบคำถามจากความคิดเห็น: ทำไม1.Sqrt()ไม่ควรถูกกฎหมาย? 1.ToString()คือ.

บางภาษาไม่อนุญาตให้มีวิธีการในประเภทค่า แต่บางภาษาสามารถ ฉันกำลังพูดถึงสิ่งเหล่านี้รวมถึง Java, ECMAScript, C # และ Python (พร้อมคำ__str__(self)จำกัดความ) เช่นเดียวกับฟังก์ชั่นอื่น ๆ เช่นceil(), floor()ฯลฯ


18
คุณเสนอภาษานี้ในภาษาใด จะ1.sqrt()ใช้ได้ไหม

20
ในหลายภาษา (เช่นจาวา) คู่เป็นแบบดั้งเดิม (สำหรับเหตุผลด้านประสิทธิภาพ) ดังนั้นพวกเขาจึงไม่มีวิธี
Richard Tingle

45
ดังนั้นประเภทตัวเลขควรจะเต็มไปด้วยฟังก์ชั่นทางคณิตศาสตร์ที่เป็นไปได้ที่สามารถนำไปใช้กับพวกเขา?
D Stanley

19
FWIW ผมคิดว่าSqrt(x)รูปลักษณ์มากเป็นธรรมชาติมากขึ้นกว่าx.Sqrt() หมายความว่า prepending ฟังก์ชั่นที่มีระดับในบางภาษาที่ฉันตกลงกับที่ ถ้ามันมีวิธีการเช่นนั้นx.GetSqrt()จะมีความเหมาะสมมากขึ้นเพื่อแสดงให้เห็นว่ามันกลับมีค่ามากกว่าการปรับเปลี่ยนเช่น
D Stanley

23
คำถามนี้ไม่สามารถเป็นผู้ไม่เชื่อเรื่องภาษาในรูปแบบปัจจุบัน นั่นคือรากเหง้าของปัญหา
risingDarkness

คำตอบ:


20

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

.NET มีเพียงหนึ่งคงMath.Sqrtวิธีการที่ทำหน้าที่ในdoubledoubleและผลตอบแทน doubleอะไรก็ได้ที่คุณส่งผ่านไปมันจะต้องเป็นนักแสดงหรือส่งเสริมให้

double sqrt2 = Math.Sqrt(2d);

ในทางกลับกันคุณมีสนิมซึ่งแสดงการดำเนินการเหล่านี้เป็นฟังก์ชั่นในประเภท :

let sqrt2 = 2.0f32.sqrt();
let higher = 2.0f32.max(3.0f32);

แต่ Rust ยังมีไวยากรณ์การเรียกฟังก์ชันสากล (มีคนพูดถึงก่อนหน้านี้) เพื่อให้คุณสามารถเลือกสิ่งที่คุณต้องการ

let sqrt2 = f32::sqrt(2.0f32);
let higher = f32::max(2.0f32, 3.0f32);

1
เป็นที่น่าสังเกตว่าใน. NET คุณสามารถเขียนวิธีการขยายได้ดังนั้นหากคุณต้องการให้การติดตั้งนี้เป็นจริงคุณx.Sqrt()สามารถทำได้ public static class DoubleExtensions { public static double Sqrt( this double self) { return Math.Sqrt(self); } }
Zachary Dow

1
นอกจากนี้ในC # 6มันอาจจะเป็นแค่msdn.microsoft.com/en-us/library/sf0df423.aspxSqrt(x)
Den

65

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

แต่การเอาสแควร์รูทของจำนวนเต็มนั้นใช้ได้เช่นกันและเราไม่ต้องการบังคับให้ทุกคนแปลงเป็นสองเท่าเพื่อใช้สแควร์รูท ดังนั้นเราจึงย้ายไปที่intและเริ่มออกแบบ มันกลับมาอะไร? เราสามารถคืนค่าintและทำให้มันทำงานได้เฉพาะกับสี่เหลี่ยมที่สมบูรณ์แบบหรือปัดเศษผลลัพธ์ให้ใกล้เคียงที่สุดint(ไม่สนใจการอภิปรายเกี่ยวกับวิธีการปัดเศษที่เหมาะสมในตอนนี้) แต่จะเกิดอะไรขึ้นถ้ามีคนต้องการผลลัพธ์ที่ไม่ใช่จำนวนเต็ม? เราควรมีสองวิธี - วิธีหนึ่งคืนค่าintและคืนค่าdouble(ซึ่งไม่สามารถทำได้ในบางภาษาโดยไม่ต้องเปลี่ยนชื่อ) doubleดังนั้นเราจึงตัดสินใจว่ามันควรจะกลับมาเป็น ตอนนี้เราดำเนินการ แต่การนำไปปฏิบัตินั้นเหมือนกับสิ่งที่เราใช้double. เราคัดลอกและวางหรือไม่ เราใช้วิธีการอินสแตนซ์กับ a doubleและเรียกใช้อินสแตนซ์นั้นไหม ทำไมไม่ใส่ตรรกะในวิธีการห้องสมุดที่สามารถเข้าถึงได้จากทั้งสองชั้นเรียน เราจะเรียกห้องสมุดและฟังก์ชั่น MathMath.Sqrt

ทำไมMath.Sqrtฟังก์ชั่นคงที่:

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

เรายังไม่ได้ระบุข้อโต้แย้งอื่น ๆ :

  • มันควรจะตั้งชื่อGetSqrtเพราะมันส่งกลับค่าใหม่มากกว่าการปรับเปลี่ยนอินสแตนซ์?
  • เกี่ยวกับSquareอะไร Abs? Trunc? Log10? Ln? Power? Factorial? Sin? Cos? ArcTan?

6
ไม่ต้องพูดถึงความสุขของ1.sqrt()vs 1.1.sqrt()(ghads ที่ดูน่าเกลียด) พวกเขามีคลาสพื้นฐานร่วมกันหรือไม่ สัญญาสำหรับsqrt()วิธีการคืออะไร?

5
@MichaelT ตัวอย่างที่ดี ฉันอ่านสี่ครั้งเพื่อเข้าใจสิ่งที่1.1.Sqrtเป็นตัวแทน ฉลาด.
D Stanley

17
ฉันไม่ชัดเจนจากคำตอบนี้จริง ๆ ว่าคลาสแบบคงที่ช่วยด้วยเหตุผลหลักของคุณได้อย่างไร หากคุณมี double Sqrt (int) และ double Sqrt (double) ในคลาส Math ของคุณคุณมีสองตัวเลือก: แปลง int เป็น double จากนั้นเรียกใช้เป็น double version หรือคัดลอกและวางวิธีที่มีการเปลี่ยนแปลงที่เหมาะสม (ถ้ามี ) แต่นั่นเป็นตัวเลือกเดียวกันกับที่คุณอธิบายสำหรับอินสแตนซ์รุ่น เหตุผลอื่นของคุณ (โดยเฉพาะอย่างยิ่งหัวข้อย่อยที่สามของคุณ) ฉันเห็นด้วยมากขึ้น
Ben Aaronson

14
-1 คำตอบนี้ไร้สาระสิ่งใดที่เกี่ยวข้องกับการนิ่ง คุณจะต้องตัดสินใจเลือกคำตอบสำหรับคำถามเดียวกันเหล่านั้นไม่ว่าจะด้วยวิธีใด(และ "[ด้วยฟังก์ชันแบบคงที่] การใช้งานเหมือนกัน" เป็นเท็จหรืออย่างน้อยก็ไม่เป็นความจริงมากกว่าที่จะเป็นวิธีการเช่น .. )
BlueRaja - Danny Pflughoeft

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

25

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

สองสามภาษาช่วยให้เราสามารถกำหนดฟังก์ชันที่ใช้ไวยากรณ์การเรียกใช้เมธอด แต่จริง ๆ แล้วจะถูกส่งแบบสแตติก ตัวอย่างวิธีการใน C # 3.0 หรือใหม่กว่าเป็นตัวอย่าง วิธีการที่ไม่ใช่เสมือน (เช่นค่าเริ่มต้นสำหรับวิธีการใน C ++) เป็นกรณีอื่นแม้ว่า C ++ จะไม่สนับสนุนวิธีการในประเภทดั้งเดิม แน่นอนคุณสามารถสร้างคลาส wrapper ของคุณเองใน C ++ ที่ตกแต่งประเภทดั้งเดิมด้วยวิธีการต่าง ๆ โดยไม่ต้องมีค่าใช้จ่ายรันไทม์ อย่างไรก็ตามคุณจะต้องแปลงค่าเป็นประเภท wrapper ด้วยตนเอง

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


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

  • สัญกรณ์คณิตศาสตร์นั้นขึ้นอยู่กับตัวดำเนินการและฟังก์ชันไม่ใช่วิธีการ การแสดงออกเช่นจะปรากฏคนต่างด้าวมากขึ้นกับผู้ใช้งานมากมายกว่า42.sqrt sqrt(42)ในฐานะผู้ใช้ที่เน้นเรื่องคณิตศาสตร์ฉันต้องการความสามารถในการสร้างโอเปอเรเตอร์ของตัวเองผ่านทางไวยากรณ์ดอทเมธอด
  • หลักการความรับผิดชอบเดี่ยวสนับสนุนให้เรา จำกัด จำนวนการปฏิบัติงานที่เป็นส่วนหนึ่งของประเภทการดำเนินงานที่จำเป็น เมื่อเทียบกับการคูณคุณต้องมีรากที่สองอย่างน่าทึ่ง ถ้าภาษาของคุณมีจุดมุ่งหมายเฉพาะสำหรับ anlysis สถิติแล้วให้พื้นฐานมากขึ้น (เช่นการดำเนินงานmean, median, variance, std, normalizeในรายการที่เป็นตัวเลขหรือฟังก์ชันแกมมาสำหรับตัวเลข) จะมีประโยชน์ สำหรับภาษาที่ใช้งานทั่วไปสิ่งนี้จะลดน้ำหนักอินเตอร์เฟส การแยกการดำเนินการที่ไม่จำเป็นไปยังเนมสเปซที่แยกต่างหากทำให้ผู้ใช้ส่วนใหญ่สามารถเข้าถึงประเภทนี้ได้มากขึ้น

Python เป็นตัวอย่างที่ดีของภาษาทุกอย่าง - เป็น - วัตถุที่ใช้สำหรับการบีบอัดจำนวนมาก สเกลาร์ NumPy มีหลายสิบวิธี แต่ sqrt ยังไม่เป็นหนึ่งในนั้น ส่วนใหญ่ของพวกเขาเป็นสิ่งที่ชอบtransposeและmeanที่นั่นมีเพียงเพื่อให้อินเตอร์เฟซที่เหมือนกันกับอาร์เรย์ NumPy ซึ่งเป็นโครงสร้างข้อมูลเทียมจริง
user2357112 รองรับ Monica

7
@ user2357112: สิ่งนี้คือ NumPy นั้นเขียนด้วยส่วนผสมของ C และ Cython ด้วยกาว Python ไม่อย่างนั้นมันจะไม่เร็วอย่างที่มันเป็น
เควิน

1
ฉันคิดว่าคำตอบนี้กระทบอย่างใกล้ชิดกับการประนีประนอมในโลกแห่งความจริงที่ผ่านมาหลายปีแห่งการออกแบบ ในข่าวอื่น ๆ เป็นเรื่องที่สมเหตุสมผลหรือไม่ที่จะสามารถทำ "Hello World" .Max () เนื่องจากส่วนขยาย LINQ ทำให้เราและมองเห็นได้อย่างชัดเจนใน Intellisense คะแนนโบนัส: ผลลัพธ์คืออะไร โบนัสโบนัสผลลัพธ์ใน Unicode คืออะไร ...
Andyz Smith

15

ฉันจะได้รับแรงบันดาลใจจากความจริงที่ว่ามีฟังก์ชั่นคณิตศาสตร์สำหรับวัตถุประสงค์พิเศษมากมายและแทนที่จะเติมข้อมูลคณิตศาสตร์ทุกประเภทที่มี (หรือชุดย่อยแบบสุ่ม) ของฟังก์ชันเหล่านั้นที่คุณวางไว้ในคลาสยูทิลิตี้ มิฉะนั้นคุณอาจทำให้เสียคำแนะนำเครื่องมือเติมข้อมูลอัตโนมัติของคุณหรือคุณบังคับให้คนดูในสองสถานที่ ( sinมีความสำคัญพอที่จะเป็นสมาชิกDoubleหรืออยู่ในMathชั้นเรียนพร้อมกับสายเลือดเหมือนhtanและexp1p?)

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


ฉันหวังว่านักออกแบบภาษาจะไม่สนใจคำแนะนำเครื่องมืออัตโนมัติ แล้วจะเกิดอะไรขึ้นMath.<^space>? เคล็ดลับเครื่องมืออัตโนมัติที่สมบูรณ์จะถูกปนเปื้อนด้วยเช่นกัน ฉันคิดว่าย่อหน้าที่สองของคุณน่าจะเป็นคำตอบที่ดีกว่าที่นี่
Qix

@Qix พวกเขาทำ แม้ว่าคนอื่น ๆ ที่นี่อาจเรียกว่า "การทำให้อินเทอร์เฟซป่อง"
Aleksandr Dubinsky

6

คุณสังเกตได้อย่างถูกต้องว่ามีความสมมาตรที่อยากรู้อยากเห็นที่นี่

ไม่ว่าฉันจะพูดsqrt(n)หรือn.sqrt()ไม่สำคัญพวกเขาทั้งสองแสดงออกในสิ่งเดียวกันและสิ่งที่คุณต้องการนั้นเป็นเรื่องของรสนิยมส่วนตัวมากกว่าสิ่งอื่นใด

นั่นคือเหตุผลที่มีข้อโต้แย้งที่แข็งแกร่งจากนักออกแบบภาษาบางคนเพื่อให้ไวยากรณ์ทั้งสองสามารถใช้แทนกันได้ ภาษาการเขียนโปรแกรม D แล้วช่วยนี้อยู่ภายใต้คุณลักษณะที่เรียกว่าUniform Function Call ไวยากรณ์ คุณลักษณะที่คล้ายกันนอกจากนี้ยังได้รับการเสนอให้เป็นมาตรฐานใน C ++ ในขณะที่Mark Amery ชี้ให้เห็นในความคิดเห็น Python ก็อนุญาตเช่นกัน

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

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


Python รองรับไวยากรณ์เหล่านี้ทั้งสองแล้ว ทุกวิธีที่ไม่คงที่ใช้selfเป็นพารามิเตอร์แรกและเมื่อคุณเรียกวิธีการเป็นคุณสมบัติของอินสแตนซ์แทนที่จะเป็นคุณสมบัติของคลาสที่อินสแตนซ์ที่ได้รับการส่งผ่านโดยปริยายเป็นอาร์กิวเมนต์แรก ดังนั้นฉันสามารถเขียน"foo".startswith("f")หรือstr.startswith("foo", "f")และฉันสามารถเขียนหรือmy_list.append(x) list.append(my_list, x)
Mark Amery

@ MarkAmery จุดดี นี่ไม่ใช่สิ่งที่รุนแรงอย่างที่ D หรือข้อเสนอ C ++ ทำ แต่มันเหมาะกับแนวคิดทั่วไป ขอบคุณสำหรับการชี้!
ComicSansMS

3

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

คุณพูดถึงวิธี ToString () - ที่นี่คุณอาจต้องการแทนที่วิธีนี้ดังนั้นคลาส (sub) จะถูกแทนด้วยวิธีอื่น ๆ เช่น String เป็นคลาสพาเรนต์ ดังนั้นคุณทำให้มันเป็นวิธีการอินสแตนซ์


2

ใน Java มีเสื้อคลุมสำหรับทุกประเภทพื้นฐาน
และประเภทพื้นฐานไม่ใช่ประเภทคลาสและไม่มีฟังก์ชั่นสมาชิก

ดังนั้นคุณมีตัวเลือกดังต่อไปนี้:

  1. รวบรวมฟังก์ชั่นผู้ช่วยทั้งหมดเหล่านั้นให้เป็นแบบโปร - ฟอร์Mathมา
  2. ทำให้มันเป็นฟังก์ชั่นคงที่บนกระดาษห่อที่สอดคล้องกัน
  3. ทำให้มันเป็นฟังก์ชั่นสมาชิกบนกระดาษห่อที่สอดคล้องกัน
  4. เปลี่ยนกฎของ Java

ลองออกกฎข้อที่ 4 เพราะ ... Java คือ Java และสมัครพรรคพวกยอมรับว่าเป็นอย่างนั้น

ทีนี้เราสามารถแยกตัวเลือก 3 ออกได้เพราะในขณะที่การจัดสรรวัตถุค่อนข้างถูกมันไม่ฟรีและการทำเช่นนั้นซ้ำแล้วซ้ำอีกจะเพิ่มขึ้น

สองลงหนึ่งที่ยังคงฆ่า: ตัวเลือกที่ 2 ก็เป็นความคิดที่ดีเพราะมันหมายความว่าทุกฟังก์ชั่นจะต้องดำเนินการสำหรับทุกประเภทหนึ่งไม่สามารถพึ่งพาการแปลงแบบกว้างเพื่อเติมช่องว่างหรือความไม่สอดคล้องจะเจ็บจริง ๆ
และการดูที่java.lang.Mathมีจำนวนมากของช่องว่างโดยเฉพาะอย่างยิ่งชนิดที่มีขนาดเล็กกว่านั้นintdouble

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

กลับไปที่ตัวเลือก 4 มีบางอย่างในทิศทางนั้นเกิดขึ้นจริงในภายหลัง: คุณสามารถขอให้คอมไพเลอร์พิจารณาสมาชิกสแตติกทั้งหมดของคลาสใด ๆ ที่คุณต้องการเมื่อทำการแก้ไขชื่อเป็นเวลานานแล้ว import static someclass.*;

นอกจากนี้ภาษาอื่น ๆ ก็ไม่มีปัญหาเช่นกันเพราะพวกเขาไม่มีอคติต่อฟังก์ชั่นฟรี (เลือกใช้ namespaces) หรือประเภทเล็ก ๆ น้อย ๆ


1
พิจารณาความสุขของการใช้รูปแบบMath.min()ในทุกประเภทเสื้อคลุม

ฉันพบข้อผิดพลาด # 4 Math.sqrt()ถูกสร้างขึ้นในเวลาเดียวกันกับส่วนที่เหลือของ Java ดังนั้นเมื่อการตัดสินใจที่จะทำให้ sqrt () ในMathนั้นไม่มีความเฉื่อยทางประวัติศาสตร์ของผู้ใช้ Java ที่ "ชอบอย่างนั้น" แม้ว่าจะมีปัญหาไม่มากนักsqrt()แต่พฤติกรรมที่บรรทุกเกินพิกัดของMath.round()นั้นก็โหดร้าย ความสามารถในการใช้ไวยากรณ์สมาชิกที่มีค่าประเภทfloatและdoubleจะหลีกเลี่ยงปัญหานั้น
supercat

2

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

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

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

บางภาษาอาจใช้สิ่งนี้กับคลาสและวิธีการส่วนตัว:

class Int {
    public Int add(Int x) {
      // Do something with the bits
    }
    private List<Boolean> getBits() {
      // ...
    }
}

บางส่วนมีระบบโมดูล:

signature INT = sig
  type int
  val add : int -> int -> int
end

structure Word : INT = struct
  datatype int  = (* ... *)
  fun add x y   = (* Do something with the bits *)
  fun getBits x = (* ... *)
end

บางคนมีขอบเขตคำศัพท์:

(defun getAdder ()
   (let ((getBits (lambda (x) ; ...
         (add     (lambda (x y) ; Do something with the bits
     'add))

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

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


ไม่มีอะไรจะป้องกันภาษาจากการอนุญาตให้วิธีการแบบคงที่จะถูกเรียกว่าอย่างใดอย่างหนึ่งโดยใช้สมาชิกไวยากรณ์ (เช่นวิธีการขยาย C # หรือ vb.net) หรือกับรูปแบบของลำดับสมาชิก เพื่อให้ข้อดีของ Intellisense ในการแสดงรายการเฉพาะฟังก์ชั่นที่เหมาะสมสำหรับการโต้แย้งหลัก แต่หลีกเลี่ยงความกำกวมกับโอเปอเรเตอร์ของสมาชิกจริง)
supercat

-2

ใน Java และ C # ToString เป็นวิธีการของวัตถุรูทของลำดับชั้นของคลาสดังนั้นทุกวัตถุจะใช้วิธีการ ToString สำหรับ Integertype นั้นเป็นเรื่องธรรมดาที่การติดตั้ง ToString จะใช้วิธีนี้

ดังนั้นคุณคิดผิด ประเภทค่าเหตุผลที่นำไปใช้กับ ToString ไม่ใช่ว่าบางคนมีลักษณะ: เฮ้เรามีวิธีการ ToString สำหรับประเภทค่า เป็นเพราะ ToString มีอยู่แล้วและเป็น "สิ่งที่เป็นธรรมชาติที่สุด" สำหรับการส่งออก


1
แน่นอนมันเป็นตัดสินใจคือการตัดสินใจที่จะมีobjectมีToString()วิธีการ นั่นคือในคำพูดของคุณ "มีคนชอบ: เฮ้ลองมาใช้วิธี ToString สำหรับประเภทค่า"
Residuum

-3

แตกต่างจาก String.substring, Number.sqrt ไม่ใช่คุณลักษณะของตัวเลข แต่เป็นผลลัพธ์ใหม่โดยยึดตามหมายเลขของคุณ ฉันคิดว่าการส่งหมายเลขของคุณไปยังฟังก์ชันกำลังสองนั้นง่ายกว่า

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


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