Lợi ích của lập trình hướng đối tượng so với lập trình thủ tục là gì?


77

Tôi đang cố gắng hiểu sự khác biệt giữa các ngôn ngữ thủ tục như C và các ngôn ngữ hướng đối tượng như C ++. Tôi chưa bao giờ sử dụng C ++, nhưng tôi đã thảo luận với bạn bè về cách phân biệt hai loại này.

Tôi đã nói với C ++ có các khái niệm hướng đối tượng cũng như chế độ công khai và riêng tư để định nghĩa các biến: những thứ C không có. Tôi chưa bao giờ phải sử dụng những thứ này trong khi phát triển các chương trình trong Visual Basic.NET: lợi ích của những thứ này là gì?

Tôi cũng được thông báo rằng nếu một biến là công khai, nó có thể được truy cập ở bất cứ đâu, nhưng không rõ nó khác với biến toàn cầu trong ngôn ngữ như C. Cũng không rõ biến riêng tư khác với biến cục bộ như thế nào.

Một điều khác tôi đã nghe là, vì lý do bảo mật, nếu một chức năng cần được truy cập thì nó nên được kế thừa trước tiên. Trường hợp sử dụng là quản trị viên chỉ nên có nhiều quyền như họ cần chứ không phải mọi thứ, nhưng có vẻ như một điều kiện cũng sẽ hoạt động tốt:

if ( login == "admin") {
    // invoke the function
}

Tại sao điều này không lý tưởng?

Cho rằng dường như có một cách thủ tục để làm mọi thứ hướng đối tượng, tại sao tôi phải quan tâm đến lập trình hướng đối tượng?



11
Bản đồ mô hình lập trình này có thể giúp bạn.
AProgrammer

26
+1 để chống lại một số downvote. Nếu một đồng nghiệp hỏi tôi một câu hỏi như vậy, tôi có thể sẽ có một số lo ngại và thậm chí có thể hạ bệ anh ta (giả sử có bất kỳ loại mũi tên xuống bên cạnh anh ta). Tuy nhiên, câu hỏi này dường như được hỏi bởi một kỹ sư phần mềm trong tương lai và có vẻ như anh ta đã dành thời gian suy nghĩ và thảo luận về chủ đề này trước khi đăng. Tôi bỏ phiếu giúp anh ta hơn là sa thải.
DXM

14
@DXM Ý tưởng tuyệt vời! Mũi tên Downvote / upvote nổi xung quanh đồng nghiệp ... Điều đó sẽ làm việc kỳ diệu.
yannis

2
Đối số truy cập chuẩn: Cũng có một cách biên dịch để làm mọi thứ bạn có thể làm trong C, vậy tại sao bạn nên quan tâm đến C? (Gợi ý: Đó là tất cả về nâng cao t ông mức độ trừu tượng C ++ quản lý để làm điều này với ra hy sinh hầu hết tốc độ C của IMO đó là lý do chính cho sự thành công của C ++...)
SBI

Câu trả lời:


135

Tất cả các câu trả lời cho đến nay đều tập trung vào chủ đề câu hỏi của bạn như đã nêu, đó là "sự khác biệt giữa c và c ++" là gì. Trong thực tế, có vẻ như bạn biết sự khác biệt là gì, bạn chỉ không hiểu tại sao bạn lại cần sự khác biệt đó. Vì vậy, sau đó, các câu trả lời khác đã cố gắng giải thích OO và đóng gói.

Tôi muốn hòa nhập với một câu trả lời khác, bởi vì dựa trên các chi tiết của câu hỏi của bạn, tôi tin rằng bạn cần phải lùi lại vài bước.

Bạn không hiểu mục đích của C ++ hoặc OO, bởi vì với bạn, dường như ứng dụng của bạn chỉ cần lưu trữ dữ liệu. Dữ liệu này được lưu trữ trong các biến. "Tại sao tôi muốn biến một biến không thể truy cập? Bây giờ tôi không thể truy cập nó nữa! Bằng cách đặt mọi thứ ở chế độ công khai hoặc tốt hơn trên toàn cầu, tôi có thể đọc dữ liệu từ bất cứ đâu và không có vấn đề gì." - Và bạn đã đúng, dựa trên quy mô của các dự án bạn đang viết, có lẽ không có nhiều vấn đề (hoặc có, nhưng bạn chưa nhận thức được chúng).

Tôi nghĩ rằng câu hỏi cơ bản mà bạn thực sự cần phải trả lời là: "Tại sao tôi lại muốn ẩn dữ liệu? Nếu tôi làm điều đó, tôi không thể làm việc với nó!" Và đây là lý do:

Giả sử bạn bắt đầu một dự án mới, bạn mở trình soạn thảo văn bản của mình và bạn bắt đầu viết các chức năng. Mỗi khi bạn cần lưu trữ một cái gì đó (để ghi nhớ nó sau này), bạn tạo một biến. Để làm cho mọi thứ đơn giản hơn, bạn làm cho các biến của bạn toàn cầu. Phiên bản đầu tiên của ứng dụng của bạn chạy tuyệt vời. Bây giờ bạn bắt đầu thêm nhiều tính năng. Bạn có nhiều chức năng hơn, dữ liệu nhất định bạn đã lưu trữ từ trước khi cần phải đọc từ mã mới của bạn. Các biến khác cần được sửa đổi. Bạn tiếp tục viết nhiều chức năng hơn. Những gì bạn có thể nhận thấy (hoặc, nếu không, bạn hoàn toàn sẽ nhận thấy trong tương lai) là, khi mã của bạn trở nên lớn hơn, bạn sẽ mất nhiều thời gian hơn và lâu hơn để thêm tính năng tiếp theo. Và khi mã của bạn trở nên lớn hơn, việc thêm các tính năng trở nên khó hơn và khó hơn mà không phá vỡ thứ gì đó đã từng làm việc. Tại sao? Bởi vì bạn cần phải nhớ tất cả những gìcác biến toàn cục của bạn đang lưu trữ và bạn cần nhớ nơi tất cả chúng đang được sửa đổi. Và bạn cần nhớ chức năng nào là ổn để gọi theo thứ tự chính xác và nếu bạn gọi chúng theo thứ tự khác , bạn có thể gặp lỗi vì các biến toàn cục của bạn chưa hoàn toàn hợp lệ. Bạn đã bao giờ chạy vào đây?

Làm thế nào lớn là các dự án điển hình của bạn (dòng mã)? Bây giờ hình ảnh một dự án lớn gấp 5000 đến 50000 lần dự án của bạn. Ngoài ra, có nhiều người làm việc trong đó. Làm thế nào mọi người trong nhóm có thể nhớ (hoặc thậm chí nhận thức được) những gì tất cả các biến đó đang làm?

Những gì tôi mô tả ở trên là một ví dụ về mã được ghép hoàn hảo. Và kể từ buổi bình minh của thời gian (giả sử thời gian bắt đầu từ ngày 1 tháng 1 năm 1970), loài người đã tìm mọi cách để tránh những vấn đề này. Cách bạn tránh chúng là bằng cách chia mã của bạn thành các hệ thống, hệ thống con và các thành phần và giới hạn số lượng hàm có quyền truy cập vào bất kỳ phần dữ liệu nào. Nếu tôi có 5 số nguyên và một chuỗi đại diện cho một loại trạng thái nào đó, tôi có thể làm việc với trạng thái này dễ dàng hơn không nếu chỉ có 5 hàm đặt / nhận các giá trị? hoặc nếu 100 hàm đặt / nhận các giá trị tương tự? Ngay cả khi không có ngôn ngữ OO (ví dụ C), mọi người vẫn đang nỗ lực tách biệt dữ liệu khỏi dữ liệu khác và tạo ranh giới phân tách sạch giữa các phần khác nhau của mã. Khi dự án đạt đến một kích thước nhất định, việc lập trình trở nên dễ dàng, "tôi có thể truy cập biến X từ hàm Y" không,

Đây là lý do tại sao các khái niệm OO đã được giới thiệu và đây là lý do tại sao chúng rất mạnh mẽ. Chúng cho phép bạn ẩn dữ liệu của mình khỏi bạn và bạn muốn thực hiện nó một cách có chủ đích, bởi vì càng ít mã nhìn thấy dữ liệu đó, càng có ít cơ hội, khi bạn thêm tính năng tiếp theo, bạn sẽ phá vỡ thứ gì đó. Đây là mục đích chính cho các khái niệm đóng gói và lập trình OO. Chúng cho phép bạn chia các hệ thống / hệ thống con của chúng tôi thành các hộp nhỏ hơn, đến mức, cho dù dự án tổng thể lớn đến đâu, một tập hợp các biến đã cho chỉ có thể được truy cập bởi 50-200 dòng mã và đó là điều đó! Rõ ràng có nhiều hơn nữa để lập trình OO, nhưng, về bản chất, đây là lý do tại sao C ++ cung cấp cho bạn các tùy chọn khai báo dữ liệu / hàm là riêng tư, được bảo vệ hoặc công khai.

Ý tưởng lớn thứ hai trong OO là khái niệm về các lớp trừu tượng. Mặc dù các ngôn ngữ thủ tục cũng có thể có sự trừu tượng hóa, trong C, một lập trình viên phải nỗ lực có ý thức để tạo ra các lớp như vậy, nhưng trong C ++, khi bạn khai báo một lớp, bạn sẽ tự động tạo một lớp trừu tượng (tùy thuộc vào việc có trừu tượng hóa hay không sẽ thêm hoặc loại bỏ giá trị). Bạn nên đọc / nghiên cứu thêm về các lớp trừu tượng và nếu bạn có nhiều câu hỏi hơn, tôi chắc chắn diễn đàn này sẽ rất vui khi trả lời những câu hỏi đó.


5
Câu trả lời tuyệt vời, dường như đạt mức phù hợp cho câu hỏi
Carlos

29
+1 ... chủ yếu dành cho dòng "Và kể từ buổi bình minh của thời gian (giả sử thời gian bắt đầu từ ngày 1 tháng 1 năm 1970) ..."
CaffGeek

4
@Chad - Tôi đã nghĩ rằng một mình dòng đó sẽ ghi cho tôi ít nhất một điểm :)
DXM

Có một cách để đối phó với vấn đề quy mô này mà bạn nói đến trong mô hình thủ tục. Nó được gọi là chức năng. Nhưng cách tốt để giải thích vấn đề.
annoying_squid

@DXM - Tôi không chắc mình đã hiểu câu trả lời đúng chưa. Chúng ta cũng có thể đạt được chức năng set / get tương tự trong Lập trình thủ tục. Chúng ta có thể viết các hàm set / get trong C để sửa đổi / lấy biến toàn cục. Cũng sử dụng phương pháp này, chúng tôi đang giới hạn số lượng hàm đang sửa đổi các biến toàn cục. Và ngay cả trong OOP, nếu chúng ta cũng sử dụng các phương thức set / get, chúng ta sẽ sử dụng các phương thức này từ bên ngoài đối tượng để thay đổi các giá trị.
kadina

10

Hmm ... có lẽ tốt nhất là sao lưu và cố gắng đưa ra một số ý tưởng về mục đích cơ bản của lập trình hướng đối tượng. Phần lớn mục đích của lập trình hướng đối tượng là cho phép tạo ra các kiểu dữ liệu trừu tượng. Đối với một ví dụ thực sự đơn giản mà bạn chắc chắn quen thuộc, hãy xem xét một chuỗi. Một chuỗi thường sẽ có một bộ đệm để chứa nội dung của chuỗi, một số hàm có thể hoạt động trên chuỗi (tìm kiếm trong đó, truy cập các phần của chuỗi, tạo chuỗi, v.v.) Nó cũng sẽ (ít nhất là điển hình) theo dõi độ dài (hiện tại) của chuỗi và (có thể) kích thước của bộ đệm để nếu (ví dụ) bạn tăng kích thước của chuỗi từ 1 lên 1000000, nó sẽ biết khi nào cần thêm bộ nhớ để giữ dung lượng lớn hơn Nội dung.

Các biến đó (bộ đệm, độ dài hiện tại và kích thước bộ đệm) là riêng tư đối với chuỗi, nhưng chúng không cục bộ đối với một hàm cụ thể. Mỗi chuỗi có nội dung có độ dài cụ thể, vì vậy chúng tôi cần theo dõi nội dung / độ dài đó cho chuỗi đó. Ngược lại, cùng một chức năng (ví dụ: để trích xuất một chuỗi con) có thể hoạt động trên nhiều chuỗi khác nhau vào các thời điểm khác nhau, do đó dữ liệu không thể cục bộ cho từng chức năng.

Như vậy, chúng tôi kết thúc với một số dữ liệu riêng tư đối với chuỗi, do đó, chỉ có thể truy cập (trực tiếp) vào các hàm chuỗi. Thế giới bên ngoài có thể lấy chiều dài của chuỗi bằng cách sử dụng hàm chuỗi, nhưng không cần biết gì về phần bên trong của chuỗi để có được chuỗi. Tương tự, nó có thể sửa đổi chuỗi - nhưng một lần nữa, nó thực hiện điều đó thông qua các hàm chuỗi và chỉ họ trực tiếp sửa đổi các biến đó cục bộ thành đối tượng chuỗi.

Về bảo mật, tôi lưu ý rằng mặc dù điều này là hợp lý tương tự, nhưng đó không phải là cách mọi thứ thực sự hoạt động. Cụ thể, quyền truy cập trong C ++ đặc biệt không nhằm đáp ứng các loại yêu cầu tương tự như quyền truy cập trong một hệ điều hành. Một hệ điều hành được cho là thực thi các hạn chế để (ví dụ) một người dùng bình thường không thể làm những việc dành riêng cho quản trị viên. Ngược lại, kiểm soát truy cập trong C ++ chỉ nhằm mục đích ngăn ngừa tai nạn. Theo thiết kế, bất cứ ai muốn có thể bỏ qua chúng khá dễ dàng. Chúng có cùng thứ tự như đánh dấu một tệp chỉ đọc để bạn không vô tình xóa nó. Nếu bạn quyết định xóa tệp, việc thay đổi nó từ chỉ đọc thành đọc-ghi là chuyện nhỏ; tất cả cài đặt thành chỉ đọc sẽ khiến bạn ít nhất nghĩ về nó một giây và quyết định xóa tệp để nó không bị xóa do vô tình chỉ nhấn nhầm phím không đúng lúc.


6

OOP so với C không thực sự về bất kỳ điều gì bạn đã thảo luận. Chủ yếu là về mã đóng gói vào các khu vực không / không thể vô tình (hoặc đôi khi thậm chí cố ý) ảnh hưởng lẫn nhau.

C cho phép bạn cơ bản chạy bất kỳ chức năng từ bất cứ đâu. OOP ngăn chặn điều đó bằng cách nhóm các phương thức vào các lớp và chỉ cho phép bạn sử dụng các phương thức bằng cách tham chiếu lớp chứa chúng. Vì vậy, một lợi thế tiềm năng lớn của OOP là bạn có nhiều khả năng sắp xếp mã tốt hơn mà không cần nhiều kinh nghiệm để nói với bạn rằng bạn nên làm.


4
-1. Không có gì độc quyền trong C làm cho tất cả các chức năng toàn cầu. Bạn có thể khai báo bất kỳ hàm tĩnh nào và do đó giới hạn phạm vi của nó đối với tệp cục bộ. C không khác với C ++, Java, v.v. ở khía cạnh này. Ngoài ra, OOP không phải là về cú pháp ngôn ngữ, bạn có thể viết các chương trình OO bằng C, mặc dù chúng sẽ thô hơn một chút so với các ngôn ngữ có hỗ trợ cú pháp cho OO. Và ngược lại: bạn không nhận được OOP chỉ vì bạn đã chọn một ngôn ngữ hỗ trợ OO. Hướng đối tượng là một phong cách lập trình , không phải là một tính năng ngôn ngữ.

@Lundin: Trong khi bạn đúng về mặt kỹ thuật, bạn đã bỏ lỡ điểm. Các ngôn ngữ OOP làm cho hành vi mặc định của nó hoạt động theo cách OOP. C không.
John Fisher

1
Không có gì trong các ngôn ngữ OO buộc bạn phải làm điều đó. Ví dụ, tôi đã thấy vô số chương trình C ++ tối nghĩa mà không có bất kỳ OO nào đáng nói. Tương tự, nếu bạn chưa có manh mối về OO nhưng cố gắng thực hiện các lớp học, di sản, v.v., có khoảng 100% cơ hội tạo ra một chương trình lộn xộn.

@Lundin: Tôi không nghĩ C ++ là một ví dụ công bằng. Đó là (hoặc ít nhất là) có nghĩa là có thể biên dịch các chương trình C mà không cần sửa đổi (nhiều). Thêm các lớp trên cùng không làm cho nó trở thành ngôn ngữ OOP ở cấp độ C # hoặc Java, nhưng nó cho phép loại phát triển đó.
John Fisher

Bạn cũng có thể viết các chương trình không phải OO bằng Java, chỉ cần hack đi trong một tệp chính lớn ... OO vẫn không cụ thể về ngôn ngữ, nếu lập trình viên không biết về OO, không có ngôn ngữ nào trên thế giới sẽ lưu chúng.

4

Một lớp được viết tốt phải là một "hòn đảo tin cậy" nhỏ: Bạn có thể sử dụng nó và cho rằng nó là "điều đúng đắn" và nó bảo vệ bạn khỏi những cạm bẫy thông thường. Điều đó làm cho một lớp tốt trở thành một khối xây dựng, có thể tái sử dụng nhiều hơn như một loạt các hàm và biến, có thể hoạt động tốt nhưng cho bạn thấy tất cả những điều xấu xí của chúng, và buộc bạn phải hiểu cách chúng hoạt động cùng nhau, cách chúng cần được khởi tạo v.v ... Một lớp tốt phải giống như phích cắm USB, trong khi giải pháp thủ tục giống như một bó dây, chip, thiếc và bit hàn.

Một điểm không được thảo luận sâu là khía cạnh giao diện / triển khai. Một giao diện mô tả hành vi, nhưng không nhận ra. Vì vậy, một giao diện danh sách mô tả khái niệmcủa một danh sách và hành vi của nó: Bạn sẽ mong đợi những thứ như phương thức thêm, xóa và kích thước. Bây giờ có rất nhiều cách khác nhau để thực hiện danh sách này, ví dụ như danh sách được liên kết hoặc sử dụng bộ đệm mảng. Sức mạnh của lập trình OO là bằng cách sử dụng một giao diện, bạn có thể suy luận về hành vi mà không biết về việc thực hiện. Truy cập các biến hoặc phương thức nội bộ sẽ phá hủy sự trừu tượng hóa này, bạn không thể thay thế một triển khai danh sách này bằng một danh sách khác và bạn không thể cải thiện việc triển khai hiện có mà không cần chạm vào mã bằng lớp. Đó là một trong những lý do chính tại sao các biến và phương thức riêng tư là cần thiết: Để bảo vệ các chi tiết nội bộ của việc triển khai, vì vậy sự trừu tượng vẫn còn nguyên.

OO thậm chí còn tiến thêm một bước: Ví dụ: đối với các thư viện, bạn có thể xác định giao diện cho những thứ thậm chí chưa tồn tại và viết mã hoạt động với giao diện đó. Người dùng có thể viết các lớp thực hiện giao diện và sử dụng các dịch vụ do thư viện cung cấp. Điều này cho phép mức độ linh hoạt không thể có với lập trình thủ tục.


Khái niệm giao diện không phải là duy nhất cho các ngôn ngữ hướng đối tượng. Tôi nghĩ, một yếu tố lớn hơn là trong các ngôn ngữ không phải OOP, gần như tất cả các hàm được sử dụng trong một mô-đun phải thuộc cùng một không gian tên toàn cầu. Điều này đòi hỏi một trong hai tên hàm tiền tố để chỉ ra những gì chúng hành động hoặc nếu không có nhiều phương thức phát âm tương tự làm những việc hoàn toàn khác nhau (ví dụ SetLocationcó thể được sử dụng để di chuyển Monster, trong khi SetPositioncó thể di chuyển PopupWindowMovecó thể được sử dụng để điều chỉnh vị trí của a DisplayCursor). Cố gắng tìm đúng phương pháp "di chuyển" ...
supercat

... có thể được thực hiện dễ dàng hơn nhiều nếu khi một người viết MyMonstor->trình soạn thảo chỉ hiển thị một danh sách các phương thức có thể áp dụng cho những thứ thuộc loại Monster. Nếu có nhiều hàng chục loại khác nhau, mỗi loại hỗ trợ khoảng chục thao tác, việc cắt giảm 90% sự lộn xộn trong danh sách phương pháp bằng 90% có thể giúp giảm năng suất rất nhiều.
supercat

Cuộc đụng độ tên @supercat là một vấn đề ngôn ngữ không phải là vấn đề không thuộc về OOP. Mặt khác, các không gian tên có vấn đề vì về cơ bản trình biên dịch cần đổi tên hàm tự động hoặc xáo trộn nó. Vậy tại sao không làm bằng tay?
annoying_squid

@annoying_squid: Những gì OOP cung cấp là khả năng sử dụng hiệu quả loại đối số chính của funciton để chọn không gian tên. Nếu tôi có một biến itkiểu SuperFancyWhizBang, việc gọi một trong SuperFancyWhizBangcác phương thức trên itkhông yêu cầu viết ra kiểu đó SuperFancyWhizBang; nói it.woozle()sẽ chỉ đạo trình biên dịch để tự động tìm kiếm woozlebên trong SuperFancyWhizBang.
supercat

3

Có một cách để làm mọi thứ với máy Turing hoặc tối thiểu bằng ngôn ngữ lắp ráp cho mã máy mà chương trình C hoặc C ++ cuối cùng sẽ biên dịch thành.

Vì vậy, sự khác biệt không phải là về những gì mã có thể làm, mà là về những gì mọi người có thể làm.

Mọi người mắc sai lầm. Rất nhiều.

OOP giới thiệu một mô hình và một cú pháp giúp giảm kích thước và mật độ xác suất của không gian của các lỗi mã hóa có thể có của con người. Đôi khi, bằng cách phạm sai lầm bất hợp pháp đối với một loại đối tượng dữ liệu nhất định (chẳng hạn như đó không phải là phương thức được khai báo cho đối tượng đó). Đôi khi bằng cách làm cho sai lầm dài dòng hơn, hoặc trông kỳ quặc về phong cách so với việc sử dụng ngôn ngữ chính tắc. Đôi khi bằng cách yêu cầu một giao diện với các cách sử dụng ít nhất quán có thể không nhất quán hoặc vướng mắc (công khai so với riêng tư). Vân vân.

Dự án càng lớn, khả năng sai lầm càng cao. Mà một lập trình viên mới có thể không được tiếp xúc nếu chỉ có kinh nghiệm với các chương trình nhỏ. Do đó, sự bối rối tiềm tàng tại sao OOP có giá trị.


2

Câu hỏi của bạn có vẻ nhiều hơn về mục đích của OOP hơn là sự khác biệt. Khái niệm trong bài viết của bạn là Đóng gói; và đóng gói tồn tại để hỗ trợ THAY ĐỔI. Khi các lớp khác đang truy cập vào nội bộ của bạn, việc sửa đổi chúng mà không phá vỡ chúng trở nên khó khăn. Trong OOP, bạn cung cấp một giao diện (thành viên công cộng) thông qua đó bạn cho phép các lớp khác tương tác với lớp của bạn và bạn ẩn các phần bên trong của mình để chúng có thể được thay đổi một cách an toàn.


Chỉ cần sử dụng các nguyên mẫu chức năng. Đó là sự gói gọn.
annoying_squid

2

Bất kể nơi nào tôi đọc các biến riêng tư đều không thể được truy cập trong khi các biến công khai có thể là lý do tại sao không biến công khai thành toàn cầu và riêng tư như địa phương có gì khác biệt? sử dụng thực sự của công cộng và tư nhân là gì? xin vui lòng không nói rằng nó có thể được sử dụng bởi tất cả mọi người, tôi cho rằng tại sao chúng ta không sử dụng một số điều kiện và thực hiện các cuộc gọi?

Tôi hy vọng bạn không bao giờ muốn có nhiều hơn một chuỗi trong ứng dụng của mình. Tôi cũng hy vọng rằng các biến cục bộ của bạn vẫn tồn tại giữa các lệnh gọi hàm. Những điều này có thể giống nhau về khả năng tiếp cận nhưng về thời gian sử dụng và cách sử dụng khác? Chúng hoàn toàn không giống nhau.


1

Như nhiều người đã nói, bất kỳ chương trình nào, một khi được biên dịch, sẽ được chuyển thành mã nhị phân và, như một chuỗi nhị phân có thể được sử dụng để biểu diễn một số nguyên, bất kỳ chương trình nào cuối cùng cũng chỉ là một số. Tuy nhiên, việc xác định số lượng bạn cần có thể khá khó khăn và đó là lý do tại sao các ngôn ngữ lập trình cấp cao xuất hiện. Ngôn ngữ lập trình chỉ là mô hình của mã lắp ráp mà cuối cùng chúng tạo ra. Tôi muốn giải thích cho bạn sự khác biệt giữa lập trình thủ tục và lập trình OO bằng tài liệu rất hay này về Lập trình định hướng theo ngữ cảnh http://www.jot.fm/issues/su_2008_03/article4/

như bạn có thể thấy từ hình ảnh này, được mô tả trong bài báo, lập trình thủ tục chỉ cung cấp một chiều để liên kết một đơn vị tính toán với một tên. Ở đây, các cuộc gọi thủ tục hoặc tên được ánh xạ trực tiếp đến việc thực hiện thủ tục. Trong hình-một cuộc gọi m1 không có lựa chọn nào khác ngoài việc thực hiện thủ tục m1 duy nhất.

Lập trình hướng đối tượng thêm một chiều khác cho độ phân giải tên với lập trình thủ tục. Ngoài phương thức hoặc tên thủ tục, việc gửi tin nhắn sẽ khiến người nhận tin nhắn phải cân nhắc khi tra cứu một phương thức. Trong hình-b, chúng ta thấy hai triển khai của phương thức m1. Việc lựa chọn phương thức thích hợp không chỉ phụ thuộc vào tên tin nhắn m1, mà còn cả người nhận tin nhắn thực tế, ở đây là Ry.

Điều này thực sự cho phép đóng gói và mô đun hóa.

nhập mô tả hình ảnh ở đây

Hình-c cuối cùng là về lập trình hướng đối tượng mở rộng việc gửi phương thức hướng đối tượng theo một chiều khác.

Hy vọng điều này đã giúp bạn suy nghĩ tại OOP từ một góc nhìn khác.


0

(+1) Đặt câu hỏi về điều gì đó bạn không hiểu, điều đó tốt, ngay cả khi nó nghe có vẻ ngớ ngẩn.

Sự khác biệt là lập trình hướng đối tượng và lớp. "Plain C", hoạt động với dữ liệu & chức năng. "C ++" thêm các khái niệm "đối tượng & lớp", cộng với một số khái niệm thứ cấp liên quan.

Tuy nhiên, tôi ủng hộ các nhà phát triển tìm hiểu "Plain C" trước "C ++". Hoặc "Pascal thủ tục" trước "Object Pascal".

Nhiều nhà phát triển nghĩ rằng sinh viên chỉ nên dạy một thứ.

Ví dụ, các giáo viên cũ không nhận được OO và chỉ dạy "Cấu trúc đơn giản C".

Hoặc giáo viên "hipster" chỉ dạy OO, nhưng không dạy "Plain C", bởi vì "bạn không cần nó". Hoặc cả hai, mà không quan tâm đến thứ tự giảng dạy.

Tôi nghĩ rằng, sinh viên nên được dạy cả "Đồng bằng có cấu trúc C" và "Hướng đối tượng C (C ++)". Với "Plain C", đầu tiên và "C ++", sau đó.

Trong thế giới thực, bạn cần học cả hai mô hình (cộng với các mô hình khác, như "chức năng").

Suy nghĩ các chương trình có cấu trúc như một "đối tượng" lớn, đơn lẻ, có thể giúp ích.

Bạn cũng nên nhấn mạnh vào không gian tên ("mô-đun"), trong cả hai ngôn ngữ, nhiều giáo viên chỉ bỏ qua nó, nhưng, điều quan trọng của nó.


Không gian tên và quá tải chỉ làm cho chương trình khó hiểu hơn. Nó làm cho bối cảnh quá trình xác định nhạy cảm. Khi bạn thấy foo()trong C ++, nó có thể là một hàm toàn cục, một hàm trong không gian tên hiện tại, một hàm trong không gian tên mà bạn sử dụng using, một phương thức, một phương thức được kế thừa và nếu nó trong hàm gọi: nó có thể nằm trong một không gian tên có thể được giải quyết bằng cách tra cứu tên dựa trên đối số và điều tương tự là đúng với Java và C #. Trong C, nó chỉ có thể là một hàm tĩnh trong tệp nguồn hiện tại hoặc một hàm từ một tiêu đề.
Calmarius

Viết MODULE_Foo () ở mọi nơi có thể là một mớ hỗn độn thị giác, nhưng ít nhất bạn biết chính xác đó là chức năng gì.
Calmarius

@Calmarius giải pháp, rõ ràng, là không đặt tên bất cứ điều gì foo .

0

Trong một từ, quản lý dự án. Ý tôi là C ++ giúp tôi thực thi các quy tắc về cách mã của tôi được người khác sử dụng. Làm việc trên một dự án 5,5 triệu dòng tôi thấy lập trình hướng đối tượng rất hữu ích. Một ưu điểm khác là trình biên dịch làm cho tôi (và mọi người khác) tuân theo các quy tắc nhất định và bắt các lỗi nhỏ trong thời gian biên dịch. Tất cả những lợi thế về lý thuyết cũng có nhưng tôi chỉ muốn tập trung vào những thứ thực tế hàng ngày. Sau khi tất cả nó biên dịch thành mã máy.


-1

Lập trình hướng đối tượng là lập trình thủ tục, có hộp.

Trong PP, bạn có một hộp, một trạng thái, trở nên cực kỳ lớn khi dự án phát triển, khiến các hiệu ứng phụ xuất hiện mỗi khi bạn quên một chút nhỏ của trạng thái lớn đó.

Trong OO, bạn có nhiều hộp, nhiều tiểu bang và khi dự án phát triển, các hộp phát triển một chút và số lượng hộp tăng lên rất nhiều.

Việc nhìn vào các hộp nhỏ hơn vẫn dễ dàng hơn, dễ có ảo ảnh về toàn bộ bức tranh, nhưng thực sự gần như không thể, vì nhìn vào các lớp và giao diện ẩn các chi tiết thực hiện có thể có sự phân nhánh quan trọng.

Trong lập trình chức năng, bạn có nhiều hộp chức năng và quyết định rằng mọi hàm đều có một mục nhập (tham số) và một lối thoát (trả về), hoàn toàn không có quyền truy cập nào khác vào bối cảnh bên ngoài.

Do không có trạng thái và không có tác dụng phụ (theo thiết kế), bạn có thể phân tích một cách an toàn bất kỳ chức năng nào tách biệt với toàn bộ và biết 100% nó sẽ hoạt động như thế nào trong mọi tình huống.

Bởi vì bạn là mã quyền anh bởi các đơn vị logic đại diện cho các hành động, nên cũng chỉ có một hộp cho mỗi hành động thông thường.

Điều này sẽ thu nhỏ mã của bất kỳ dự án quy mô lớn nào bằng một yếu tố rất lớn so với OOP, điều này thúc đẩy việc ẩn nhiều hàm tương tự trên toàn bộ cơ sở mã trong các lớp khác nhau.

Điều này cũng sẽ đánh bại PP rất xa vì bạn có thể phát triển dự án lâu hơn vì không còn trạng thái XXXXXXXL để theo dõi.

Tóm lại, PP có lẽ là cách đơn giản nhất để tiếp cận một chương trình đơn giản và FP có lẽ là cách đơn giản nhất để tiếp cận một chương trình phức tạp.

Nếu bạn tham gia vào mục tiêu thống nhất tất cả các cơ sở mã và cải thiện việc sử dụng lại mã, thì nên sử dụng FP, vì đó là mô hình duy nhất có ý nghĩa ở quy mô rất lớn, cũng như mô hình duy nhất có khả năng tái sử dụng 100% (bạn có thể chỉ cần sao chép dán một chức năng và sử dụng nó ở một nơi khác, không có chi phí nào).

Và bạn nhận được thử nghiệm đơn vị đáng tin cậy 100% miễn phí.

Và bạn không cần phải viết "private static of_doom genius awesome_1".

Và bạn có được song song miễn phí.


-3

Một sự khác biệt câu đơn giản là C ++ là C với các lớp. (Mặc dù nó là nhiều hơn bây giờ) tôi không lý do tại sao bạn không muốn tìm hiểu những khác biệt giữa hai bằng cách đọc một bài viết tuyệt vời trên C ++ tại Wikipedia .... . Bài viết này sẽ giúp bạn rất nhiều: - C ++ (Wikipedia)

Ngoài ra googling về vấn đề này sẽ giúp. Yêu cầu người ngẫu nhiên để giải thích điều này có thể là khó khăn. IMHO, một người hiểu rõ hơn bằng cách đọc hơn là hỏi ai đó


Tôi đã đọc những thứ đó nhưng họ chỉ nói nơi chúng được sử dụng nhưng vẫn không giải quyết được câu hỏi của tôi.
niko

Tôi đã không đặt câu hỏi mà không đặt bất kỳ nỗ lực nào mà tôi đã googled nhưng vẫn không thể hiểu được sự khác biệt vì vậy tôi đã gặp stackoverflow để giúp tôi với những điều này
niko 16/11/11

1
@niko, bạn đang làm tôi sai ở đây Điều tôi muốn nói là bạn nên cố gắng hiểu sự khác biệt giữa hai bằng cách đọc. Hỏi bạn bè của bạn không tốt. Bởi vì họ sẽ cung cấp sự hiểu biết của riêng họ mà có thể không làm bạn buồn cười. Nhưng đừng lo lắng, có những đồng nghiệp tuyệt vời ở đây, họ chắc chắn sẽ giúp bạn ra ngoài :-)
Pankaj Upadhyay

2
Tôi đã không downvote, nhưng đã bị cám dỗ rất nhiều tại "C ++ là C với các lớp". Những người trong chúng ta, những người thực sự có thể làm C ++, chúng tôi cố gắng loại bỏ điều đó ra khỏi đầu mọi người.
DeadMG

1
@Pankaj: Đúng vậy. Đó C với các lớp học. Nó chắc chắn không phải là C với các Class nữa, và gọi nó như vậy là gần 30 năm lỗi thời. C ++ đã đi một chặng đường rất dài kể từ đó. Những người viết mã C ++ bây giờ không bao giờ, bao giờ đề cập đến nó theo cách đó. Nó khuyến khích những thói quen xấu nhất và ấn tượng sai.
DeadMG
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.