Phương thức vs Chức năng vs Thủ tục


107

Câu hỏi đơn giản, nhưng tôi thường nghe ba thuật ngữ được định nghĩa với sự hung dữ như vậy, nhưng tôi đã biết nó có nghĩa là những điều khác nhau trong những năm qua.

Các định nghĩa "chính xác" của "Thủ tục", "Phương thức", "Hàm", "Chương trình con", v.v là gì?


4
bạn từ bỏ "thói quen"
mefisto

1
@teresko: Tôi nghĩ "chương trình con" là phổ biến hơn.
mk12

Câu trả lời:


108

Tôi sẽ có một câu trả lời khác ở đây: thực tế mà nói, thực sự không có gì khác biệt , ngoại trừ một chút rằng "phương thức" thường đề cập đến một chương trình con liên kết với một đối tượng trong các ngôn ngữ OO.

Các thuật ngữ "thủ tục, hàm, chương trình con, chương trình con và phương thức" tất cả thực sự có nghĩa giống nhau: một chương trình con có thể gọi được trong một chương trình lớn hơn. Nhưng thật khó để đưa ra một định nghĩa nắm bắt tất cả các cách sử dụng biến thể của các thuật ngữ này, bởi vì chúng không được sử dụng nhất quán trên các ngôn ngữ lập trình hoặc mô hình.

Bạn có thể nói một hàm trả về một giá trị. Chà, hàm C sau đây không trả về giá trị:

void f() { return; }

... nhưng tôi nghi ngờ bạn sẽ tìm thấy bất cứ ai gọi đó là thủ tục.

Chắc chắn, trong Pascal, các thủ tục không trả về giá trị và hàm trả về giá trị, nhưng đó chỉ là sự phản ánh về cách Pascal được thiết kế. Trong Fortran, một hàm trả về một giá trị và một chương trình con trả về nhiều giá trị. Tuy nhiên, không ai trong số này thực sự cho phép chúng tôi đưa ra định nghĩa "phổ quát" cho các thuật ngữ này.

Trên thực tế, thuật ngữ "lập trình thủ tục" dùng để chỉ cả một nhóm ngôn ngữ, bao gồm C, Fortran và Pascal, chỉ một trong số đó thực sự sử dụng thuật ngữ "thủ tục" để chỉ bất cứ điều gì.

Vì vậy, không ai trong số này là thực sự phù hợp. Ngoại lệ duy nhất có lẽ là "phương thức", dường như được sử dụng gần như hoàn toàn với các ngôn ngữ OO, đề cập đến một chức năng được liên kết với một đối tượng. Mặc dù, thậm chí điều này không phải lúc nào cũng nhất quán. Ví dụ, C ++ thường sử dụng thuật ngữ "hàm thành viên" thay vì phương thức, (mặc dù thuật ngữ "phương thức" đã len lỏi vào ngôn ngữ C ++ trong số các lập trình viên.)

Vấn đề là, không ai trong số này là thực sự phù hợp. Nó chỉ đơn giản phản ánh thuật ngữ được sử dụng bởi bất kỳ ngôn ngữ nào đang thịnh hành tại thời điểm đó.


Đó chính xác là những gì tôi nghĩ câu trả lời là. (Đáng lẽ tôi nên thêm "chương trình con" như một biến thể khác trong nhận thức muộn.) Tôi có thể hỏi: Tại sao bạn không tìm thấy ai gọi hàm C đó là "Thủ tục" không? Bởi vì về mặt kỹ thuật không chính xác, hoặc vì thuật ngữ "thủ tục" hiện không còn thịnh hành?
Django Reinhardt

7
Các lập trình viên C sử dụng thuật ngữ "hàm" đơn giản vì các nhà thiết kế của C đã sử dụng thuật ngữ đó.
Charles Salvia

15
Chúng ta đừng ném em bé ra ngoài bằng nước tắm. Chỉ vì thuật ngữ này không được sử dụng với tính nhất quán đầy đủ, không có nghĩa là các thuật ngữ khác nhau không có ý nghĩa khác nhau. Các định nghĩa của @ Bruce và @ Frank được công nhận rộng rãi, không bình dị. Thực tế là các ý nghĩa không phổ biến là quan trọng, nhưng nó không chứng minh bước nhảy vọt đến "thực tế mà nói, thực sự không có sự khác biệt". (@Django)
LarsH

9
Loại kép cho C ++, gọi các phương thức là "hàm thành viên", hàm gọi Java và C # là "phương thức tĩnh".
Jörg W Mittag

2
Câu trả lời của Bruce chắc chắn là câu trả lời bạn nên làm nếu bạn chưa quen với lập trình. Định nghĩa của ông sẽ hoàn toàn chính xác, 99% thời gian. Nhưng tôi đã tìm kiếm nhiều hơn một câu trả lời kỹ thuật / lý thuyết. Đôi khi các lập trình viên mới hơn chỉ biết tên miền riêng của họ và nhấn mạnh rằng đó là tất cả. Trong thực tế, có những lập trình viên làm việc ngày nay vẫn sử dụng các ngôn ngữ cũ hơn và không "sai" khi sử dụng các định nghĩa khác nhau. Đó là điều tôi quan tâm nhất.
Django Reinhardt

67

Một hàm trả về một giá trị, nhưng một thủ tục thì không.

Một phương pháp tương tự như một chức năng, nhưng là nội bộ để một phần của một lớp. Phương pháp thuật ngữ được sử dụng hầu như chỉ trong lập trình hướng đối tượng.


8
Không chính xác nội bộ. Một phương thức là bất kỳ hàm hoặc thủ tục nào là một phần của lớp.
Scott Whitlock

8
Vì vậy, một "Thủ tục lưu trữ" trong SQL không trả về bất kỳ giá trị nào? Điều gì về một "Thủ tục" trong một cái gì đó như Pascal? Là định nghĩa của bạn dựa trên xu hướng hiện tại hay chúng nên được coi là định nghĩa phổ quát? Cảm ơn!
Django Reinhardt

3
@Django: Trong Pascal, một thủ tục không thể có giá trị trả về và hàm phải có giá trị trả về. Trong một số ngôn ngữ khác, thuật ngữ có thể được sử dụng lỏng lẻo hơn.
Bruce Alderman

1
FWIW, FORTRAN đã có SUBROUTINE và CHỨC NĂNG từ những ngày đầu, sự khác biệt là SUBROUTINE không trả lại giá trị. Tôi không nhớ về ALGOL, mà Pascal có nguồn gốc từ.
David Thornley

2
@ 3p1c_d3m0n Chắc chắn đúng là functionhoàn thành cả hai vai trò trong JS, nhưng các hàm JS thực hiện tất cả trả về. Khi một câu lệnh return không có giá trị, giá trị này được ngầm định undefined. Khi không có câu lệnh return, trình thông dịch sẽ thêm câu lệnh return. Bí truyền, có thể, nhưng nó phù hợp với định nghĩa được đưa ra ở đây. Đây là lý do tại sao var x = function() {}();là hợp pháp trong JS; nếu không phải là trả về ngầm, thì đây sẽ là một lỗi, vì nó sẽ có trong Pascal.
Dấu chấm phẩy

52

Một chức năng là một cái gì đó mà phải mất một loạt các đầu vào và trả về một hoặc nhiều giá trị. Nếu các giá trị được trả về hoàn toàn được xác định bởi các đầu vào và hàm không có bất kỳ tác dụng phụ nào (ghi nhật ký, có thể hoặc gây ra thay đổi trạng thái bên ngoài chính nó), thì đó được gọi là hàm thuần túy.

Một thủ tục là một hàm không trả về giá trị. Đặc biệt, điều này có nghĩa là một quy trình chỉ có thể gây ra tác dụng phụ. (Điều đó có thể bao gồm việc thay đổi một tham số đầu vào!)

Một phương pháp là một chức năng mà đóng trên một tập hợp các biến, đó là một kết thúc . Nó không có hoặc nhiều tham số đầu vào, có quyền truy cập vào bộ biến này và trả về 0 hoặc nhiều giá trị. Trong các ngôn ngữ OO, các phương thức này được gắn vào các đối tượng hoặc các lớp.

Trong hầu hết các ngôn ngữ OO chính thống, các biến đóng này được gọi là các trường thành viên hoặc biến đối tượng của một đối tượng. Một phương thức có thể là một hàm thuần túy, một hàm không tinh khiết hoặc một thủ tục.

Định nghĩa sau dẫn đến sự tương ứng object = struct + bao đóng .


5
Vì vậy, một đối tượng là một tập hợp các biến và một tập hợp các bao đóng trên các biến phổ biến này. Về cơ bản, các ngôn ngữ hướng đối tượng luôn có sự đóng cửa và không ai biết? Quan điểm thú vị! +1
Giorgio

1
Tôi không tin hầu hết các phương pháp gần hơn bất cứ điều gì. foo.doSomething()không tham số. Nó có một tham số (đối tượng foo) với một số đường cú pháp. Một bao đóng sẽ có thể tham chiếu đối tượng của nó mà không cần một tham số như vậy. Điều đó không có nghĩa là các phương thức không thể là các bao đóng, chỉ là hầu hết là không và rằng OO là không đủ cho một ngôn ngữ để hỗ trợ các bao đóng.
8bittree

3
foo.doSomething()đóng trên foobiến. Bất kỳ tuyên bố trong doSomethingcó thể truy cập foothông qua thishoặc self, tùy thuộc vào ngôn ngữ của bạn. Đây là định nghĩa của "gần hơn". Các lớp gần với các biến thành viên của chúng, do đó (bỏ qua "OO là gì"), OO là đủ. Điều này khá nổi tiếng trong tài liệu ...
Frank Shearar

1
Ơ, không. Thấy ít foo.ở phía trước foo.doSomething()? Đó là bạn truyền doSomething()một tham số. Chỉ vì nó không ở giữa dấu ngoặc đơn không có nghĩa là nó không phải là một tham số. Các thishoặc selfbên trong phương pháp này là đường đơn giản là cú pháp để tham khảo thông số đó.
8bittree

1
@FrankShearar, tôi muốn nói rằng chỉ có hai sự khác biệt rõ ràng hợp lý trong điện toán - dữ liệu và hướng dẫn. Ngay cả điều đó đi ra ngoài cửa sổ trong trường hợp (bất thường) của mã tự sửa đổi. Trong OO, những gì thường được gọi là "phương thức" (hoặc "hàm thành viên") không cần phải là phương thức hoặc chức năng theo định nghĩa của bạn - tất cả những từ này được sử dụng chung là từ đồng nghĩa với nghĩa chung và có thể hoán đổi cho nhau. "Hàm không tinh khiết" mà sự tồn tại mà bạn ám chỉ, chỉ đơn giản là một từ đồng nghĩa khác (và cũng dài nhất và có biệt ngữ) cho cùng một khái niệm chung về "chỉ dẫn".
Steve

14

Bruce có một câu trả lời tốt . Tôi sẽ thêm, về mặt ngữ nghĩa:

  • Một thủ tục nên "làm một cái gì đó" cho các đối số hoặc gây ra một số tác dụng phụ khác (ví dụ printf)
  • Một hàm nên (a) trả lời một câu hỏi về các đối số hoặc (b) tính toán một giá trị mới dựa trên các đối số
  • Một phương thức hàm sẽ trả lời một câu hỏi về trạng thái của đối tượng
  • Một phương thức thủ tục sẽ thay đổi trạng thái của đối tượng

Câu trả lời chính xác! Chỉ cần một bổ sung nhỏ: A procedure should "do something" to the arguments- hoặc gây ra một số tác dụng phụ khác (ví dụ printf).
Allon Guralnek

1
@ ALLon Lưu ý rằng printftrả về một giá trị - số lượng ký tự được in - vì vậy về mặt kỹ thuật nó là một chức năng.
Sjoerd

@Sjoerd Tôi không đồng ý rằng đó printflà một giá trị. Nó có một tác dụng phụ cụ thể bên ngoài phạm vi gọi của nó: cụ thể là I / O đối với bất kỳ đầu ra tiêu chuẩn nào mà nó được cho là. Mặc dù, Scott không nói rõ sự khác biệt này, trong các chức năng lập trình chức năng không được coi là có tác dụng phụ và có thể trả lời các câu hỏi như thể bạn có dữ liệu thực tế mà nó trả về.
Alan

4

câu trả lời chi tiết tốt ở trên; câu chuyện ngắn là tất cả các hương vị của chương trình con; ý nghĩa của mỗi thuật ngữ sẽ khác nhau tùy theo ngữ cảnh ngôn ngữ lập trình

nói chung, các hàm trả về một giá trị, nhưng chúng không phải

phương pháp là một thuật ngữ OOP chung hiện nay

trong SQL, các thủ tục được lưu trữ có đầu ra nhưng thường chỉ trả về mã lỗi, trong khi các hàm do người dùng xác định phải trả về một giá trị (có thể là tập kết quả)

một lần nữa, sự khác biệt chính xác giữa các điều khoản này phụ thuộc vào người bạn đang nói chuyện!


2

80% trình độ có liên quan trực tiếp đến việc làm quen với danh pháp,

95% năng suất là khả năng xác định những gì hữu ích tại thời điểm này mặc dù các thuật ngữ được sử dụng để mô tả nó

Tôi khá thích gọi tất cả các phương thức trong c # trừ khi tôi sử dụng MSSQL, chúng tôi đã sử dụng sproc, nhưng tất nhiên bây giờ chúng tôi sử dụng Postgres và chúng được gọi là các hàm.


13
83,5% của tất cả các số liệu thống kê được tạo thành tại chỗ ;-P
Django Reinhardt

1
Tôi phải thừa nhận, tôi cảm thấy lo lắng khi nghe ai đó nói về thuật ngữ "phương pháp" khi làm việc bằng ngôn ngữ không phải là OO. Nó dường như có mối tương quan lớn với việc chạy vào mã không thành ngữ.
Racheet

Tôi sử dụng 'Phương pháp' khi đề cập đến mã C vì nhiều lập trình viên OO mà tôi giao dịch bị suy sụp tinh thần khi nghe các quy trình hoặc chức năng. Để giải trí, nếu tôi thực sự muốn gây rối với họ, tôi có thể trao đổi các điều khoản một cách ngẫu nhiên. Nó không tốt, giống như mời một người kiểm soát vào nhà bạn ... :)
mattnz
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.