2009-02-10 79 views
28

Tôi khá mới lập trình nhưng tôi đã đọc một số cuộc thảo luận thú vị về StackOverflow về các phương pháp lập trình khác nhau. Tôi vẫn chưa rõ 100% về sự khác nhau giữa lập trình thủ tục và lập trình hướng đối tượng. Nghe có vẻ như lập trình hướng đối tượng vẫn sử dụng thủ tục (phương pháp) nhưng mọi thứ được tổ chức khác nhau bởi vì đối tượng là ngôi sao của chương trình. Nhưng có vẻ như với tôi rằng các thủ tục vẫn cho phép bạn làm tất cả những điều tương tự. Giống như trong C, bạn có thể đặt tất cả các thủ tục tương tự của bạn vào một thư viện. Vì vậy, bạn có thể không thực sự nói rằng một thư viện trong C là tương tự như một đối tượng trong C + +?Sự khác nhau giữa chương trình thủ tục và chương trình hướng đối tượng là gì?

+0

Cf. [câu hỏi SO cũ này] (http://stackoverflow.com/questions/552336/oop-vs-functional-programming-vs-procedural) – jogojapan

+1

Có thể được di chuyển đến các lập trình viên SO có lẽ – Kromster

Trả lời

13

Sự khác biệt giữa hai điều này là tinh tế nhưng quan trọng.

Trong chương trình thủ tục, các mô-đun tương tác bằng cách đọc và ghi trạng thái được lưu trữ trong cấu trúc dữ liệu được chia sẻ.

Trong một chương trình hướng đối tượng, các mô-đun ở dạng đối tượng tương tác bằng cách gửi tin nhắn đến các đối tượng khác.

+0

Tôi có một nghi ngờ. Java có phải là ngôn ngữ thủ tục không? –

6

Sự khác biệt là các đối tượng có quy trình và dữ liệu liên quan ở cùng một nơi - ngôn ngữ thủ tục sử dụng 'cấu trúc' (những thứ chứa dữ liệu liên quan) giữ dữ liệu tách biệt với các thủ tục. Hiệu quả, bất cứ điều gì bạn làm trong một ngôn ngữ OO nên có thể trong một ngôn ngữ thủ tục với một sự kết hợp của các cấu trúc và thủ tục.

Sự khác biệt chính là tâm trí đặt ra rằng một ngôn ngữ OO đặt lập trình viên.

1

Đây là câu trả lời đơn giản.

  • Trong ngôn ngữ OO thực, mã hóa thủ tục chỉ được thực hiện bên trong đối tượng.

  • C không có đối tượng và C++ là ngôn ngữ hỗ trợ đối tượng. Java mặt khác tất cả mọi thứ là một đối tượng (trừ các nguyên thủy). Mọi thứ đều được nhập.

  • Tiến trình tuyến tính xảy ra bên trong các đối tượng nhưng bản thân đối tượng chỉ là tập hợp mã và dữ liệu.
+0

'... đối với chính các đối tượng chỉ là các bộ sưu tập mã và dữ liệu. ' –

+0

@Richard, cảm ơn bạn đã chỉ ra sự thiếu sót của tôi. Tôi sẽ sửa nó. – WolfmanDragon

21

Bạn có thể lập trình theo thủ tục trong hầu hết các ngôn ngữ OO, nhưng sức mạnh của OO xuất phát từ khả năng kế thừa, đóng gói và trừu tượng hóa logic thủ tục đó. Tôi nghĩ rằng bạn là chính xác, một thư viện nên trông rất giống một lớp học. Nó phải có phạm vi riêng của nó và đóng gói logic đằng sau các hàm với các tên có ý nghĩa.

+3

Để bổ sung cho câu trả lời của bạn, thừa kế, đóng gói và đa hình là ba trụ cột của OOP. –

4

Thủ tục là một phần của sự khác biệt về thủ tục/chức năng/logic (hoặc logic) (so sánh c, lisp và prolog) giữa các cách mô tả chương trình nên làm gì.

Hướng đối tượng là trực giao với ý tưởng khác này và mô tả phương tiện nhóm các chương trình con với dữ liệu. C++ và java là các ngôn ngữ thủ tục với các tính năng hướng đối tượng; fortran77 là một ngôn ngữ thủ tục không có tính năng hướng đối tượng. Common lisp hỗ trợ định hướng đối tượng; một số lisps cũ thì không. Plain vani prolog không hỗ trợ các đối tượng, và tôi không thể đặt tên một ngôn ngữ theo định hướng logic (tôi không lập trình logic theo định hướng, nó nằm trong danh sách những thứ cần làm khi tôi một số thời gian rảnh rỗi. hầu như không lập trình chức năng).

Như những người khác đã lưu ý, tuy nhiên, tư duy hướng đối tượng thích hợp thay đổi cách bạn lập trình của mình nhiều như chuyển đổi từ thủ tục sang chức năng.


BTW-- tôi nhìn thấy "thủ tục" được sử dụng rất nhiều để phân biệt phi hướng đối tượng ngôn ngữ thủ tục từ anh em hướng đối tượng của họ, nhưng tôi nghĩ rằng đây là một cách sử dụng kém do thiếu một tính từ sạch cho "không hướng đối tượng". YMMV.

+0

"định hướng logic"? ;-P – Shog9

+0

Thay vì "hợp lý" để tránh thảm họa như "Tôi không thể đặt tên một ngôn ngữ logic ..."? Vâng tôi có thể hiểu. – dmckee

+0

@ Shog9: Điều đó có tốt hơn không? – dmckee

31

Trong chương trình thủ tục, mã là vua và dữ liệu là cấp dưới. Nói cách khác, bạn có các chương trình hoạt động trên dữ liệu và chúng thường không bị ràng buộc chặt chẽ.

Trong thế giới OO, các đối tượng là điều quan tâm chính. Một đối tượng bao gồm dữ liệu mã được phép hành động trên dữ liệu đó và chúng bị ràng buộc rất chặt chẽ. Đó là khái niệm đóng gói, ẩn thông tin.

Ví dụ, giả sử bạn có một số và bạn muốn nhân đôi số đó. Cách thực hiện thủ tục này là:

n = n * 2 

Mã ở đây khá rõ ràng nhân với 2 và lưu kết quả trở lại vào n.

Cách OO để làm điều này là để gửi một "thông báo" cho các đối tượng số nói nó sẽ tăng gấp đôi bản thân:

n.double(); 

Ưu điểm của việc này được gọi là đa hình. Điều gì xảy ra khi bạn quyết định bạn muốn có thể tăng gấp đôi chuỗi như "bob". Trong thế giới thủ tục, bạn phải cung cấp thêm mã để làm việc tăng gấp đôi nhưng bạn cũng phải gọi mã đó khác đi.

Với OO, bạn tạo một đối tượng chuỗi cũng có thể lấy thông điệp 'kép'. Mã để tăng gấp đôi một chuỗi thuộc về đối tượng chuỗi để nó biết nó phải hoạt động khác với đối tượng số. Nếu nó quyết định rằng "bob" * 2 là "bobbob", mã sẽ giống như thế:

class number:     class string: 
    int n       char array s 
    procedure double:    procedure double: 
     n = n * 2      s = string_join(s,s) 

Sau đó, bạn có thể gọi x.double() không có vấn đề gì thực tế loại x là (số hoặc chuỗi) và nó sẽ biết mã nào để chạy - điều này giúp đơn giản hóa mã của bạn. Bạn có thể tăng gấp đôi số nguyên, chuỗi, ma trận, số phức, số thực, kích thước cửa sổ trên màn hình của bạn và tất cả các loại khác nhau.

Và bạn nói đúng, thư viện C có thể được tạo ra để trông hơi giống các đối tượng. Ví dụ cổ điển là stdio.h - bạn không bao giờ quan tâm những gì một FILE* thực sự trỏ đến, chỉ thực tế là nó sẽ hoạt động theo một cách nhất định. FILE*, fopen(), fclose() và các chức năng khác là một loại các loại thể hiện khả năng I/O của C.

+0

Giải thích tuyệt vời. Tôi ngạc nhiên rằng điều này đã được chọn là câu trả lời hay nhất. Tôi nghĩ rằng điều này thực sự đóng đinh nó. –

+0

Câu hỏi: Tôi hiểu làm thế nào ví dụ của bạn đại diện cho khái niệm đa hình nhưng tôi không chắc nó thể hiện sự đóng gói như thế nào - có phải vì chức năng kép hiện được bao bọc trong một phần chức năng mô-đun nhỏ gọi là phương pháp? Ngay sau khi chúng tôi có một phương pháp, chúng tôi có đóng gói? –

+1

@WO, đóng gói là ẩn dữ liệu hoặc mã. Mã đóng gói là những gì cho phép đa hình vì mã bây giờ thuộc về đối tượng hơn là có mã bên ngoài hoạt động trên một đối tượng. Bạn nói với đối tượng phải làm gì, không phải làm thế nào để làm điều đó. Nó biết làm thế nào để làm điều đó. Encaps/polymorph được gắn chặt chẽ. – paxdiablo

8

OO chủ yếu là tập hợp ý tưởng. Bạn có thể lập trình OO trong C (nếu bạn thực sự muốn ...), và bạn hoàn toàn có thể có mã thủ tục trong C++/Java; ý tôi là, ngay cả khi bạn sử dụng các lớp trên bề mặt, nó vẫn có thể là thủ tục.

Ý tưởng đằng sau OO là trừu tượng trạng thái. Thay vì "suy nghĩ" về "nhóm dữ liệu", bạn "nghĩ" về "đối tượng", trong đó đối tượng là "giao diện" để "nhóm dữ liệu và cách xử lý dữ liệu này".

Tất cả đều mang tính triết học, vì .

Có rất nhiều điều để nói ở đây, và nó không thể được nói trong một bài SO nhỏ, vì vậy tôi sẽ để nó ở đây.

CẬP NHẬT
Như đã đề cập trong Flanagan's answer, ngôn ngữ OO thực hiện các cấu trúc mà sử dụng trừu tượng này.

Ý tôi là, bạn có thể "hack" các lớp và tính đa hình về mặt kỹ thuật về cấu trúc, hàm và con trỏ hàm.

Dưới đây là ví dụ về OO in C

0

Rất nhiều điểm thú vị đã được đề cập ở đây.

Một cách để suy nghĩ về nó là trong OO, bạn có ý tưởng về 'đối tượng' là những thứ có đặc điểm và hành vi vốn có của chúng. Họ thường có một số loại 'giao diện' công khai cung cấp một cơ chế để lấy một số thông tin về chúng, nhưng chính đối tượng đó, hay đúng hơn là 'lớp', giới hạn thông tin nào có sẵn công khai. Các bên trong của đối tượng không được tiếp xúc với công chúng bởi vì thường không cần phải biết các chi tiết bẩn 'dưới mui xe' của đối tượng. Vì vậy, các chương trình hướng đối tượng sử dụng cấu trúc này, cũng như các thứ khác.

Lập trình thủ tục thường không sử dụng việc ghép nối dữ liệu và hành vi đó vào một 'đối tượng'. Tôi đã nhìn thấy nó được thực hiện trong C trước nhưng nó không được đẹp và tham gia quá nhiều kinh doanh khỉ để gần đúng những gì người ta có thể làm với, nói, C + +.

Một trong những ý tưởng đằng sau sự phát triển theo hướng đối tượng là tôi không thể muck với dữ liệu của bạn thông qua bất kỳ phương tiện nào khác ngoài những phương tiện bạn đã cung cấp. Nếu bạn chỉ cung cấp cho tôi một giao diện tốt, bạn có thể giữ cho tôi trung thực. Bây giờ, nếu bạn đang sử dụng phương pháp thủ tục và bạn gửi cho tôi cấu trúc không có bảo vệ tích hợp, thì tôi có thể làm như tôi vui lòng và nếu tôi câm hoặc xấu, tôi có thể thay đổi những thứ bạn có thể không muốn tôi thay đổi.

Được cấp, bạn có thể phá vỡ đối tượng nếu bạn thông minh nhưng bạn phải thoát ra khỏi con đường để thực hiện việc này.

Điều này không đầy đủ, nhưng đó là một khía cạnh.

0

Cách thức C++ được triển khai chỉ làm cho lập trình OO trông rất giống lập trình thủ tục. Bạn cần phải thay đổi suy nghĩ của bạn một chút.

Trong đối tượng C++ có các phương thức chỉ là các quy trình hoạt động trên đối tượng. Nhưng trong một paradi OO thực, bạn nên nghĩ về các phương thức như các thông điệp tiềm năng mà đối tượng có thể nhận được (tức là các chữ cái). Đối tượng nhận được một thông báo (các tham số thể hiện trọng tải của thông điệp tức là nội dung của chữ cái) và thay đổi trạng thái của nó dựa trên thông báo.

9

IMHO, lập trình hướng đối tượng là một khái niệm tồn tại ở mức trừu tượng cao hơn so với lập trình thủ tục. Cả hai không loại trừ lẫn nhau trong các phương thức riêng lẻ trong một chương trình OO trông khá giống với các hàm riêng lẻ trong một chương trình thủ tục. Điều này trái ngược với, ví dụ, lập trình hàm, đòi hỏi một tư duy hoàn toàn khác. Hơn nữa, bạn có thể viết procedurally trong một ngôn ngữ OO bằng cách làm cho tất cả mọi thứ tĩnh, vv Bạn có thể là một trình biên dịch của con người và viết mã OO hiệu quả trong C bằng cách sử dụng rất nhiều con trỏ hàm và đúc con trỏ struct.

OO, sau đó, là một triết lý thiết kế và thế giới quan trọng hơn cái gì đó với một định nghĩa nghiêm ngặt. Nó đòi hỏi sự thừa kế, đa hình, v.v ... được sử dụng như các mô hình chính trong việc cấu trúc mã của bạn, và cú pháp đó được cung cấp để làm cho các biểu thức này trở nên dễ hiểu mà không cần đến các thủ thuật cấp thấp. Nó đòi hỏi bạn nghĩ về mã hoạt động trên trạng thái của một tập hợp dữ liệu như là một thuộc tính của dữ liệu, không phải là một thủ tục tồn tại bởi chính nó. Nó không phải là màu đen và trắng. Mã của bạn có thể là "nhiều hơn" hoặc "ít" OO tùy thuộc vào mức độ bạn dựa vào thừa kế, đa hình, các lớp và "phương thức như một thuộc tính dữ liệu" thế giới như một phương tiện cấu trúc và giải thích/hiểu mã của bạn.

+0

Điểm tốt về sự khác biệt giữa mã OO so với mã thủ tục và ngôn ngữ OO so với ngôn ngữ thủ tục. Upped. –

6

[tha thứ phong cách mồi, đó là muộn và tôi mệt mỏi]

thủ tục xử lý dữ liệu - dữ liệu trong, áp dụng một số chế biến, lấy dữ liệu ra

đôi khi, một số các yếu tố dữ liệu có liên quan đến một số yếu tố dữ liệu khác và thuận tiện để nhóm chúng lại với nhau thành cấu trúc dữ liệu , sau đó có thể được xử lý và giải quyết dưới dạng một đơn vị duy nhất.

tại thủ tục của chúng tôi có thể mất một cấu trúc dữ liệu như là đầu vào và thay đổi nó và/hoặc tạo ra một cấu trúc dữ liệu như sản lượng

thỉnh thoảng chúng tôi nhận thấy rằng một số thủ tục là chỉ quan tâm đến một loại cấu trúc dữ liệu; thuận tiện để nhóm các quy trình này cùng với cấu trúc dữ liệu của chúng và gọi nó là đối tượng .

mẫu để tạo đối tượng được gọi là lớp; một đối tượng được cho là một dụ của một lớp

chúng ta có thể nhận thấy rằng một lớp là rất giống nhau, nên thay vì sao chép và dán mã chúng ta để cho một lớp kế thừa từ khác: các lớp con được thừa hưởng từ lớp học siêu lớp hoặc "lớp cơ sở". Bằng cách này, lớp con có quyền truy cập vào tất cả các cấu trúc dữ liệu và thủ tục của lớp cha, và có thể tăng thêm hoặc ghi đè chúng theo những cách nhất định

nếu chúng ta lịch sự yêu cầu một đối tượng làm điều gì đó trực tiếp , điều này được gọi là tin nhắn đi qua, ngay cả khi không có 'tin nhắn' thực sự được truyền đi. Niềm vui ở đây là nhiều loại đối tượng khác nhau có thể hiểu được cùng một thông điệp, dẫn đến khái niệm về đa hình đa hình. Ví dụ: chúng tôi có thể yêu cầu nhiều loại tài liệu khác nhau để Tự in và mỗi tài liệu phản hồi một cách thích hợp.

ngôn ngữ hỗ trợ đối tượng (thông qua lớp học hoặc không) với thông báo và kế thừa được gọi là hướng đối tượng. Nếu không có thừa kế, ngôn ngữ chỉ đơn thuần là dựa trên đối tượng.

chúc bạn may mắn với việc học của mình!

+4

Điều này thật tuyệt vời! Không thể tưởng tượng nó sẽ như thế nào nếu bạn không mệt mỏi. Tôi đang tiết kiệm. –

+0

@ [Willem Obst]: Cảm ơn - nếu tôi có nhiều thời gian hơn, nó sẽ ngắn hơn ;-) –

+4

Wow!Tôi muốn nhiều giáo viên của tôi có thể giải thích những thứ rõ ràng như bạn có ở đây. Cảm ơn sự đóng góp của bạn! –

2

Dễ hiểu hơn trong ngữ cảnh, nhìn vào các trừu tượng khác được giới thiệu giữa các ngôn ngữ.

Sự khác biệt chính giữa ngôn ngữ lắp ráp và ngôn ngữ thủ tục như C hoặc Pascal là sự ra đời của khái niệm "thủ tục". Mọi người viết mã lắp ráp tạo thủ tục, nhưng khó khăn và dễ bị lỗi của nó, một ngôn ngữ thủ tục cung cấp cho bạn các công cụ để làm cho nó dễ dàng hơn.

Sự khác biệt giữa ngôn ngữ thủ tục và ngôn ngữ OO như C++ là trừu tượng "đối tượng". Những người viết "c" thường tạo ra các đối tượng khái niệm but its difficult and error prone, một ngôn ngữ OO cung cấp cho bạn các công cụ để làm cho nó dễ dàng hơn.

Những thứ như Sing# từ Microsoft (hoặc Erlang) thêm Thông báo/Quy trình trừu tượng vào ngôn ngữ. Chắc chắn, bạn có thể gửi thông điệp và quá trình tạo trong assembly, C hoặc C++ nhưng Sing # làm cho nó dễ dàng hơn.

Tất cả đều đi xuống cùng một mã máy, những phần tóm tắt này hoàn toàn dành cho bộ não của chúng ta chứ không phải máy tính.

15

Bạn đúng trong quan sát của mình rằng các chương trình hướng đối tượng dựa trên nhiều cách trên mô hình thủ tục. Bạn cũng đúng trong cú pháp đó tất cả những gì thực sự xảy ra là bạn gọi hàm. Trong thực tế, bạn có thể triển khai nhiều tính năng của các ngôn ngữ hướng đối tượng bằng cách sử dụng các cơ chế thủ tục (ví dụ: các con trỏ hàm trong C++). Do đó, bạn có thể thực hiện một thiết kế hướng đối tượng và vẫn thực hiện nó bằng một ngôn ngữ thủ tục (ví dụ như các trình biên dịch C++ cũ đã làm).

Tầm quan trọng của mô hình hướng đối tượng không nhiều trong cơ chế ngôn ngữ như trong quá trình suy nghĩ và thiết kế. Trong lập trình thủ tục, suy nghĩ là về các hoạt động và phá vỡ các hoạt động đó bằng cách sử dụng các hoạt động khác, nhóm chúng thành các mô-đun, vv Điều này có nghĩa là dữ liệu hoặc trạng thái rơi vào tầm quan trọng thứ cấp. Nó giống như suy nghĩ của các hoạt động toán học. Mô hình hướng đối tượng, mặt khác, nói rằng bạn cần suy nghĩ về trạng thái và hoạt động với nhau như một thực thể, và sau đó thiết kế chương trình của bạn dưới dạng tương tác giữa các thực thể trao đổi trạng thái và kích hoạt các hoạt động.

1

Tùy thuộc vào cách bạn xác định OOP. Trong điều khoản của OOP giống như Java, nơi bạn gọi các phương thức trên các đối tượng, lập trình thủ tục là khá giống nhau. Theo như tôi có thể nói, bạn có thể mô phỏng tất cả các nguyên tắc OOP (đóng gói, trừu tượng, đa hình, thừa kế) bằng ngôn ngữ thủ tục như C. Bằng chứng là GObject, với một số mở rộng Objective-C và nhiều triển khai ngôn ngữ OOP khác bằng C, như cPython. Điều này được thực hiện bằng cách sử dụng cấu trúc và hoạt động trên các cấu trúc đó bằng cách sử dụng các hàm:

typedef struct { 
    Object *isa; 
    String *name; 
    Date *birthday; 
} Person; 

Person *Person_new(); 
String *Person_name(Person *self); 
void Person_setName(Person *self, String *newName); 
// ... 

Giao diện rất OOP như thế nào. Nó không thực sự cho phép đa hình, nhưng nó cũng có thể. Nó rất giống với giao diện Python, ngoại trừ các thuộc tính tách biệt với "các phương thức":

class Person(object): 
    def __init__(self): 
     self._name = "" 
     self._age = datetime.datetime.now() 

    @property 
    def name(self): 
     return self._name 

    @property 
    def age(self): 
     return self._age 

Tôi đã chọn Python ví dụ vì "tự" rõ ràng, như trong ví dụ C. Nhiều ngôn ngữ OOP, như Java, trừu tượng hóa điều này.

Ngoài ra còn có OOP giống như Smalltalk, nơi thư được gửi tới đối tượng, thay vì gọi phương thức trên đối tượng. Sự khác biệt là tinh tế ở cái nhìn đầu tiên, nhưng nó cung cấp rất nhiều năng lượng và tính linh hoạt. Điều này cũng có thể được thực hiện bằng các ngôn ngữ thủ tục, như đã được chứng minh bởi Objective-C.

Lập trình hướng đối tượng không nhất thiết phải là một loại ngôn ngữ, mà là một mô hình. Các ngôn ngữ hướng đối tượng như Java, Python, Ruby, vv, cung cấp cú pháp đường để dễ dàng thao tác các đối tượng, và đây là sự khác biệt chính giữa "ngôn ngữ thủ tục" và "ngôn ngữ hướng đối tượng".

Thật vậy, một thư viện, hay đúng hơn là một tập hợp các hàm hoạt động trên một cấu trúc, giống như một đối tượng trong C++. Trong thực tế, C++ được thực hiện theo cách đó.

0

Để có một ví dụ khá rõ ràng về sự khác biệt giữa thủ tục và OO, hãy thử học Smalltalk. Trong Smalltalk, mọi thứ, và ý tôi là mọi thứ đều là một vật thể. Không có câu lệnh if hoặc các vòng lặp while. Bạn đạt được chức năng đó bằng cách gửi tin nhắn tới (a.k.a. gọi các phương thức trên) các đối tượng khác. Nó thực sự làm cho đầu của bạn quay đầu tiên, nhưng tôi nghĩ bạn sẽ nhanh chóng lúng túng những gì OO được cho là.

2

Trong một chương trình thủ tục, bạn chia một vấn đề lớn thành các vấn đề nhỏ và trừu tượng từng vấn đề nhỏ như một quy trình. Điều này được gọi là trừu tượng hóa thủ tục.

Trong các chương trình hướng đối tượng, bạn phân tích vấn đề dưới dạng một số đối tượng và tương tác giữa các đối tượng. Điều này được gọi là trừu tượng đối tượng.

2

Sự khác biệt là lập trình hướng

Thủ tục - Cung cấp cho tầm quan trọng cho thuật toán chứ không phải là data.This cách của chương trình tập trung vào thủ tục tức là phương pháp để thực hiện nhiệm vụ cụ thể và chia sẻ cấu trúc dữ liệu của họ. Nó theo cấu trúc Top-down.

ví dụ: Pascal và C

Lập trình hướng đối tượng - Cung cấp tầm quan trọng cho dữ liệu thay vì thuật toán. Nó theo cấu trúc Bottom-up.Every điều được xem như là một đối tượng. Mỗi đối tượng có cấu trúc và thủ tục dữ liệu riêng. Nó bao gồm các tính năng như ẩn dữ liệu, đa hình, đóng gói và gửi thông điệp. Người dùng thực sự không phải bận tâm những gì bên trong các đối tượng này, trong khi sử dụng chúng trong các chương trình của họ.

ví dụ: C++ và Java

Các vấn đề liên quan