เหตุใดวิธีการคงที่จึงถือว่าเป็นวิธีการ


138

ฉันกำลังเขียนคำอธิบายรหัสสำหรับหลักสูตรและบังเอิญใช้คำmethodและfunctionสลับกันไปมา ฉันตัดสินใจที่จะกลับไปแก้ไขคำพูดนั้น แต่ก็พบกับช่องโหว่ในความเข้าใจของฉัน

จากสิ่งที่ฉันเข้าใจรูทีนย่อยคือfunctionถ้ามันไม่ทำงานกับอินสแตนซ์ของคลาส (เอฟเฟกต์ถูก จำกัด ไว้ที่อินพุต / เอาท์พุตอย่างชัดเจน) และmethodถ้ามันทำงานบนอินสแตนซ์ของคลาส (มันอาจมี ออกผลข้างเคียงในกรณีที่ทำให้ไม่บริสุทธิ์)

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

ด้วยเหตุนี้จึงไม่ควรนิ่งmethodsเป็นฟังก์ชันใช่หรือไม่?

ตามความหมายของพวกเขาพวกเขาไม่ได้ดำเนินการกับกรณีเฉพาะของคลาส พวกเขา "ผูก" กับชั้นเรียนเพราะความสัมพันธ์เท่านั้น ฉันเคยเห็นไซต์ที่ดูดีสองสามแห่งที่อ้างถึงรูทีนย่อยแบบคงที่เป็น "วิธีการ" แม้ว่า ( Oracle , Fredosaurus , ProgrammingSimplified ) ดังนั้นพวกเขาทั้งหมดมองข้ามคำศัพท์หรือฉันพลาดอะไรบางอย่าง (ฉันเดาว่าเป็นอย่างหลัง) .

ฉันต้องการให้แน่ใจว่าฉันใช้ถ้อยคำที่ถูกต้อง
ใครช่วยเคลียร์เรื่องนี้ได้ไหม


2
ฉันคิดเสมอว่ามันเป็นฟังก์ชันใน php และ method ใน Java โดยทั่วไปสิ่งเดียวกันกับชื่อที่แตกต่างกัน
JK

20
มีความแตกต่างระหว่างวิทยาศาสตร์คอมพิวเตอร์เชิงทฤษฎีและวิธีการใช้ภาษา JLS ไม่มีความแตกต่างและเรียกมันว่าวิธีการ
Jeroen Vannevel


2
มันอาจจะเป็นที่สนใจดูที่คำจำกัดความของ "ฟังก์ชั่น" และ "วิธีการ" ในหลามที่มีคือความแตกต่าง: โดยทั่วไปฟังก์ชั่นเป็นก้อนของรหัสที่มีตารางสัญลักษณ์และการประชุมเรียกร้องในขณะที่วิธีการคือสิ่งที่ คุณจะได้รับเมื่อคุณใส่ฟังก์ชันลงในคลาส ความแตกต่างค่อนข้างละเอียดอ่อนแม้กับคนที่รู้จัก Python
David Z

2
เมื่อฉันเรียนรู้ทฤษฎีฉันเรียนรู้ฟังก์ชันส่งคืนค่าและขั้นตอนไม่ได้ จากนั้นฉันได้เรียนรู้ฟังก์ชันการเรียกใช้ java และวิธีการขั้นตอน ตอนนี้ฉันกำลังลองใช้งานโปรแกรม mjng และฟังก์ชั่นนั้นไม่สำคัญ เงื่อนไขเปลี่ยนความหมายตามบริบท
emory

คำตอบ:


125

คำพูดจาก8.4.3.2นี้อาจช่วยได้:

วิธีการที่จะมีการประกาศstaticจะเรียกว่าเป็นวิธีการเรียน

เมธอดที่ไม่ได้ประกาศstaticเรียกว่าอินสแตนซ์เมธอด [... ]

  • วิธีการคลาส: เชื่อมโยงกับคลาส
  • วิธีการอินสแตนซ์: เชื่อมโยงกับอินสแตนซ์

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


ดังที่กล่าวไว้ในขณะที่ "ฟังก์ชัน" ถูกต้องในทางเทคนิคในฐานะหน่วยของการดำเนินการใน Java ระบบการตั้งชื่อที่ต้องการสำหรับ Java ทั้งหมดคือ "วิธีการ" เนื่องจากฟังก์ชัน Java ทั้งหมดเป็นส่วนหนึ่งของคลาสหรืออินเทอร์เฟซ (ยกเว้น lambdas และอาจ สิ่งอื่น ๆ ที่ฉันไม่ทราบ)
Shotgun Ninja

1
Lambdas เป็นคลาสภายในที่ไม่ระบุตัวตนพร้อม@FunctionalInterfaceคำอธิบายประกอบและมี 1 วิธีภายใต้ประทุน แลมบ์ดาเป็นเพียงน้ำตาลซินแทติกและในเรื่องนี้ไม่มีอะไรใหม่
Adam Arold

1
@AdamArold Lambdas ค่อนข้างคลั่งไคล้กว่าคลาสชั้นในที่ไม่ระบุตัวตน ตัวอย่างเช่น lambdas ที่ไม่ได้จับภาพสามารถแชร์อินสแตนซ์กับการประเมินหลาย ๆ นิพจน์หนึ่ง ๆ (แต่คุณพูดถูกในท้ายที่สุดพวกเขาจะถูกรวบรวมเป็นวิธีการแบบคงที่และอินสแตนซ์)
Radiodef

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

4
ฉันอาย. ฉันมาจาก Scala และยังคงพลาดความจริงที่ว่าคลาสนั้นเป็นเหมือนวัตถุ ขอบคุณ.
Carcigenicate

80

คำตอบง่ายๆก็คือเมื่อ Java ตัดสินใจเรียกทุกอย่างว่า "วิธีการ" พวกเขาไม่สนใจเกี่ยวกับความแตกต่างระหว่างฟังก์ชันและวิธีการในวิทยาศาสตร์คอมพิวเตอร์เชิงทฤษฎี


3
ถูกตัอง. จนกว่าและรวมถึง Java 7 คุณจะไม่พบคำว่า "ฟังก์ชัน" ในข้อกำหนดภาษา
Erwin Bolwidt

4
เท่าที่ฉันชอบความเรียบง่ายของคำตอบนี้ฉันคิดว่าคำตอบของ Radiodef นั้นตรงตามความเป็นจริงมากกว่าเพราะมันกล่าวถึงประเด็นสำคัญที่คลาสนั้นทำหน้าที่เป็นวัตถุ ขอบคุณแม้ว่า
Carcigenicate

2
ที่น่าสนใจคือสิ่งนี้ขนานไปกับการตัดสินใจของภาษาก่อนหน้านี้ที่จะไม่แยกความแตกต่างระหว่างฟังก์ชันและรูทีนย่อย
Random832

4
ฉันประหลาดใจไม่น้อยที่คำตอบนี้ได้รับคะแนนโหวตเพิ่มขึ้นมากมาย ประการแรกคำตอบนี้แกล้งทำเป็นว่าไม่มีเมธอดของคลาส ประการที่สองนี่แทบจะไม่เป็นแนวคิดที่นำมาใช้ใน Java วิธีการคลาสมีอยู่แล้วใน Smalltalk ซึ่งมีมานานหลายทศวรรษก่อนที่ Java จะกลายเป็นสิ่งต่างๆ
Malcolm

1
@Malcolm ฉันต้องเห็นด้วยกับคุณ หลังจากพิจารณาคำตอบอื่นแล้วดูเหมือนว่าจะผิด ไม่ใช่ความไม่แยแสในส่วนของผู้สร้าง Java เว้นแต่ว่าพวกเขาจะไม่สนใจอย่างแท้จริง แต่ลงเอยด้วยการตั้งชื่ออย่างถูกต้องโดยไม่คำนึงถึง
Carcigenicate

26

วิธีการคงที่ไม่ได้เป็นหน้าที่อย่างแท้จริงความแตกต่างนั้นบอบบาง แต่สำคัญ

วิธีการคงใช้ป้อนพารามิเตอร์ได้รับเพียงเป็นหลักฟังก์ชั่น

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

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


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

2
คำตอบนี้ใช่เลย อย่างไรก็ตามอาจมีคนโต้แย้งว่าฟังก์ชันในหลายภาษา (ส่วนใหญ่?) สามารถเข้าถึงตัวแปรทั่วโลกได้ดังนั้นจึงมักไม่เป็นแบบไร้สัญชาติ (อินพุตเดียวกันเอาต์พุตเดียวกัน) และในกรณีของ Java static method การเข้าถึงตัวแปรคลาสอาจถือได้ว่าเทียบเท่ากับการเข้าถึงตัวแปร "global" (เช่นไม่ใช่ local to a function / method) โดยอินสแตนซ์คลาสเป็นประเภทเนมสเปซ
leonbloy

1
@leonbloy Pure Functional โปรแกรมภาษาเช่น Haskell นั้นไร้สัญชาติโดยสิ้นเชิง ไม่มีอะไรที่เรียกได้ว่าเป็นตัวแปรส่วนกลาง
Thorsten S.

17

ใน Java คลาสที่ผู้ใช้กำหนดเองเป็นอินสแตนซ์ของคลาสย่อยของ java.lang.Class

ในแง่นี้วิธีการแบบคงที่จะแนบมากับอินสแตนซ์ของคลาสแนวคิด: พวกเขาจะแนบกับอินสแตนซ์ของคลาสย่อยของ java.lang.Class

ด้วยเหตุนี้คำว่า "class method" (ชื่อทางเลือกสำหรับวิธีการคงที่ของ Java) จึงเริ่มมีความหมาย และคำว่า "class method" สามารถพบได้ในหลาย ๆ ที่: Objective C, Smalltalk และ JLS - เพื่อตั้งชื่อเพียงไม่กี่อย่าง


เป็นไปได้ไหมที่จะมีสองอินสแตนซ์ของคลาสย่อยนี้
Random832

แน่นอนคุณสามารถโหลดคลาสในคลาสโหลดเดอร์ต่างๆได้ (เหตุผลของการรับ ClassCastExceptions พร้อมข้อความ "ไม่สามารถแคสต์ CustomClass เป็น CustomClass")
dunni

2
@ Random832 - เรียงลำดับ. คุณสามารถมีสองอินสแตนซ์ (หรือมากกว่า) ของคลาสย่อยคลาสเดียวกันใน JVM เดียวกันได้ตราบใดที่อินสแตนซ์แต่ละอินสแตนซ์มีตัวโหลดคลาสแยกกัน คุณไม่สามารถสร้างอินสแตนซ์คลาสย่อยคลาสเดียวกันได้มากกว่าหนึ่งครั้งต่อ classloader มันทำให้เกิดความสับสนเล็กน้อยและการเปรียบเทียบกับแนวคิด OO แบบคลาสสิกเริ่มยืดออกไปเล็กน้อยในตอนนี้
Mike Clark

@ MikeClark ถ้าฉันทำแบบนั้นมันเหมือนกันจริงเหรอ? เช่นเดียวกับคลาสย่อยของคลาสจะเป็นคลาสเดียวกันแม้ว่าคลาสนั้นจะเป็นอินสแตนซ์ที่แตกต่างกันก็ตาม Classloaders ค่อนข้างสับสนสำหรับฉัน ฉันสามารถเรียก (โดยไม่มีการไตร่ตรอง) วิธีการแบบคงที่ของอินสแตนซ์ของคลาสตัวโหลดของคลาสหนึ่งจากอินสแตนซ์ของคลาสตัวโหลดของคลาสเดียวกันโดยมีการอ้างอิงถึงอินสแตนซ์ของคลาสเดียวกันได้หรือไม่ จะเป็นอย่างไรหากพวกเขามีวิธีการต่างๆ
Random832

1
@ Random832 "เรียงจาก?" จากจุดทฤษฎีอย่างหมดจด OO ในมุมมองของผู้ใดเป็นสองกรณีของชั้นเคยจริงๆเหมือนกัน? อย่างน้อยที่สุดสองอินสแตนซ์ที่เหมือนกันของคลาสเดียวกันจะมีแอดเดรสที่แตกต่างกัน มิฉะนั้นเราจะมีสองสิ่งได้อย่างไร? สิ่งเดียวที่เหมือนกันทุกประการคือสิ่งนั้นเอง
Mike Clark

11

ในฟังก์ชันวิทยาศาสตร์คอมพิวเตอร์มีแผนที่ชัดเจนกับวิธีคงที่ แต่ "วิธีการ" ของคลาสเป็นบิตทั่วไปเช่น "สมาชิก" (สมาชิกเขตข้อมูลสมาชิกวิธีการ) มีคำพูดเช่น

สมาชิกข้อมูลและสมาชิกเมธอดมีช่องว่างชื่อสองช่อง: .x และ. x () สามารถอยู่ร่วมกันได้

ดังนั้นเหตุผลก็คือดังที่นักปรัชญาลุดวิกวิตต์เกนสไตน์กล่าวไว้ว่าภาษาเป็นเครื่องมือที่มีบริบทต่างกัน "Method" เป็นชื่อเล่นที่ดีในการอ้างอิงด้านบนเพื่อจัดหมวดหมู่ "สมาชิก"


9

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

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

วิธีการอินสแตนซ์ (ไดนามิก)

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

วิธีคลาส (คงที่)

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


7

นี่คือคำศัพท์อีกคำหนึ่งที่ใช้Scalaเป็นตัวช่วย
ในการจำ: ใน Scala คุณมีobjects ซึ่งเป็นอินสแตนซ์เดี่ยวของคลาสที่กำหนดโดยนัย1 .

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

ดังนั้นเราจึงสามารถพูดได้ว่าเมธอดแบบคงที่ของคลาส Java A เข้าถึงสมาชิกเดียวกันกับอินสแตนซ์เดี่ยวของ Scala ซึ่งตามคำจำกัดความของคุณสมควรถูกเรียกว่าเมธอด (คงที่) ของคลาส A


การเปรียบเทียบที่ยอดเยี่ยม ฉันรู้จัก Scala ดังนั้นobjectการอ้างอิงของคุณจึงสมเหตุสมผลมาก ขอบคุณ.
Carcigenicate

2

แน่นอนความแตกต่างที่สำคัญคือ - วิธีการสามารถใช้เขตข้อมูลแบบคงที่ไม่เพียง แต่พารามิเตอร์วิธีการ แต่มีอีกอย่างหนึ่ง - ความหลากหลาย! ผลการประเมินคลาส A. doTheSameStaticMethod () และ ClassB.doTheSameStaticMehod () จะขึ้นอยู่กับคลาส ในกรณีนี้ฟังก์ชันจะไม่มีประสิทธิภาพ


1

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

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