2010-08-25 76 views
29

Có sự khác biệt nào giữa việc truyền thông điệp và lời gọi phương thức hay chúng có thể được coi là tương đương không? Điều này có lẽ là cụ thể cho ngôn ngữ; nhiều ngôn ngữ không hỗ trợ truyền thông điệp (mặc dù tất cả những ngôn ngữ tôi có thể nghĩ về các phương thức hỗ trợ) và những ngôn ngữ có thể có các triển khai hoàn toàn khác nhau. Ngoài ra, có sự khác biệt lớn trong lời gọi phương pháp tùy thuộc vào ngôn ngữ (C so với Java vs Lisp vs ngôn ngữ yêu thích của bạn). Tôi tin rằng đây là ngôn ngữ bất khả tri. Bạn có thể làm gì với phương thức được truyền mà bạn không thể thực hiện với phương thức được gọi, và ngược lại (bằng ngôn ngữ yêu thích của bạn)?Sự khác nhau giữa truyền thông điệp và lời gọi phương thức là gì?

+0

Bạn có nghĩa là "Bạn có thể làm gì với thông báo * đã truyền mà bạn không thể làm ..."? Nếu có, tôi sẽ sửa lại cho bạn. – Bevan

Trả lời

3

Có sự khác biệt nào giữa việc chuyển tin nhắn và lời gọi phương thức hay chúng có thể được coi là tương đương không?

Chúng giống nhau. Một số khác biệt:

Tin nhắn có thể được truyền đồng bộ hoặc không đồng bộ (ví dụ như sự khác biệt giữa SendMessage và PostMessage trong Windows)

Bạn có thể gửi tin nhắn mà không biết chính xác từ xa đối tượng bạn đang gửi nó cho

Đối tượng mục tiêu có thể nằm trên máy từ xa hoặc O/S.

+0

Xin lỗi vì đã giải đáp một câu trả lời trong một thời gian dài trước đây, nhưng đối với "đối tượng mục tiêu có thể nằm trên máy từ xa hoặc O/S" - thực sự là duy nhất đối với việc truyền thông điệp hay lời gọi phương thức? Nếu tôi đã hiểu được hàm ý của bạn một cách chính xác, bạn nói rằng đó là tài sản của thông điệp. Nếu vậy, lời gọi phương thức từ xa trong Java không phải là mâu thuẫn với điều này? – obfuscation

4

Chúng thực sự không giống nhau trong thực tế. Truyền thông điệp là một cách để chuyển dữ liệu và hướng dẫn giữa hai hoặc nhiều quy trình song song. Gọi phương thức là một cách để gọi một chương trình con. Đồng thời của Erlang được xây dựng trên khái niệm cũ với lập trình định hướng đồng thời của nó.

Thông báo gửi nhiều khả năng nhất liên quan đến một hình thức gọi phương thức, nhưng lời gọi phương thức không nhất thiết liên quan đến việc truyền thông điệp. Nếu nó đã làm nó sẽ là tin nhắn đi qua. Gửi tin nhắn là một hình thức thực hiện đồng bộ hóa giữa các quy trình song song. Gọi phương thức thường có nghĩa là các hoạt động đồng bộ. Người gọi đợi phương thức kết thúc trước khi nó có thể tiếp tục. Thông điệp đi qua là một hình thức của một coroutine. Phương thức gọi là một dạng của chương trình con.

Tất cả các chương trình con là coroutines, nhưng tất cả các coroutines không phải là chương trình con.

+1

"Tin nhắn đi qua" cũng có thể ám chỉ cách gọi một phương thức bằng các ngôn ngữ như Smalltalk, Objective-C và Ruby. – mipadi

+1

Có những ngôn ngữ như nghĩ về nó như là thông điệp đi qua, nhưng nó là một chương trình con có liên quan đến việc đẩy một cái gì đó trên stack trong khi đình chỉ phương thức gọi chương trình con. Việc thực hiện là ngăn xếp thông qua lời gọi phương thức mà ngụ ý người gọi bị chặn trong khi chờ đợi về thói quen gọi lại để quay trở lại. Tin nhắn đi qua không có ngữ nghĩa như vậy. Nó không phải chờ đợi cho các thói quen của nó invoking để kết thúc là quan điểm của tôi. Đó là sự khác biệt. – chubbsondubs

+0

IMO OP không thực sự thảo luận về truyền thông giữa các quá trình. –

8

như một xấp xỉ đầu tiên, câu trả lời là: không có, miễn là bạn "cư xử bình thường"

Mặc dù nhiều người nghĩ rằng đó là - về mặt kỹ thuật, nó thường là như nhau: một tra cứu cache của một mảnh mã được thực hiện cho một hoạt động cụ thể có tên (ít nhất là đối với trường hợp thông thường). Gọi tên của hoạt động là "tin nhắn" hoặc "phương pháp ảo" không tạo sự khác biệt. NHƯNG: ngôn ngữ diễn viên thực sự khác nhau: trong việc có đối tượng đang hoạt động (mọi đối tượng có hàng đợi thông điệp ngầm định và chuỗi công nhân - ít nhất là khái niệm), xử lý song song dễ xử lý hơn (google cũng "liên lạc quy trình tuần tự" để biết thêm).

NHƯNG: trong Smalltalk, có thể bọc các đối tượng để làm cho chúng giống như diễn viên, mà không thực sự thay đổi trình biên dịch, cú pháp hoặc thậm chí biên dịch lại.

NHƯNG: trong Smalltalk, khi bạn cố gắng gửi thư không bị giả mạo bởi người nhận (tức là "someObject foo: arg"), một đối tượng thư được tạo, chứa tên và đối số và thư đó -object được chuyển làm đối số cho thông báo "doesNotUnderstand". Do đó, một đối tượng có thể tự quyết định cách xử lý các thông báo chưa được thực hiện (còn gọi là một phương thức chưa được thực hiện). Nó có thể - tất nhiên - đẩy chúng vào một hàng đợi cho một quá trình công nhân để tuần tự hóa chúng ...

Tất nhiên, điều này là không thể với ngôn ngữ gõ tĩnh (trừ khi bạn sử dụng rất nhiều sự phản ánh), nhưng thực sự là một tính năng rất hữu ích. Các đối tượng proxy, tải mã theo yêu cầu, các cuộc gọi thủ tục từ xa, học và tự sửa đổi mã, các chương trình thích ứng và tự tối ưu hóa, trình bao bọc corba và dcom, hàng đợi công nhân đều được xây dựng trên lược đồ đó. Nó có thể bị lạm dụng và dẫn đến lỗi thời gian chạy - tất nhiên. Vì vậy, nó là một thanh kiếm hai mặt. Sharp và mạnh mẽ, nhưng nguy hiểm trong tay của người mới bắt đầu ...

EDIT:. Tôi viết về hiện thực ngôn ngữ ở đây (như trong Java vs Smalltalk - cơ chế không inter-process

7

IIRC, họ đã Tất cả những gì cần làm là bỏ qua, trong một khoảnh khắc, sự tương đương trực tiếp của địa chỉ được gọi với một vị trí thực tế trong bộ nhớ Từ quan điểm này, con số này đơn giản chỉ là một định danh trừu tượng xác định duy nhất một loại chức năng cụ thể mà bạn muốn gọi. các hàm trong cùng một máy, không có yêu cầu thực sự nào mà địa chỉ được gọi trực tiếp chỉ định địa chỉ vật lý (hoặc thậm chí là ảo) của hàm được gọi. Ví dụ, mặc dù hầu như không ai thực sự sử dụng chúng, các cổng nhiệm vụ chế độ được bảo vệ của Intel cho phép thực hiện cuộc gọi trực tiếp đến cổng nhiệm vụ. Trong trường hợp này, chỉ phần phân đoạn của địa chỉ được coi là địa chỉ thực - tức là, mọi lệnh gọi đến phân đoạn cổng nhiệm vụ đều kết thúc bằng cách gọi cùng một địa chỉ, bất kể giá trị được chỉ định. Nếu muốn, mã xử lý có thể kiểm tra độ lệch được chỉ định, và sử dụng nó để quyết định khi một phương thức riêng được gọi - nhưng mối quan hệ giữa offset được chỉ định và địa chỉ của hàm được gọi có thể hoàn toàn tùy ý.

Lệnh gọi hàm thành viên chỉ đơn giản là một kiểu truyền thông điệp cung cấp (hoặc ít nhất tạo điều kiện) tối ưu hóa theo hoàn cảnh chung mà máy khách và máy chủ của dịch vụ được đề cập chia sẻ một không gian địa chỉ chung. Sự tương ứng 1: 1 giữa mã định danh dịch vụ trừu tượng và địa chỉ mà tại đó nhà cung cấp dịch vụ đó cư trú cho phép một ánh xạ tầm thường, đặc biệt nhanh, từ một đến cái kia.

Đồng thời, đừng nhầm lẫn: thực tế là một cái gì đó trông như cuộc gọi hàm thành viên không ngăn nó thực sự thực thi trên máy khác hoặc không đồng bộ hoặc (thường xuyên) cả hai. Cơ chế điển hình để thực hiện điều này là chức năng proxy dịch "tin nhắn ảo" của lời gọi hàm thành thành một "thông điệp thực" có thể (ví dụ) được truyền qua mạng khi cần thiết (ví dụ, DCOM của Microsoft và CORBA) điều này khá thường xuyên).

5

Sử dụng Objective-C làm ví dụ về thông báo và Java cho phương pháp, sự khác biệt chính là khi bạn truyền thông điệp, Object quyết định cách xử lý thông báo đó (thường là kết quả trong một phương pháp thể hiện trong đối tượng được gọi). Tuy nhiên, trong Java, lời gọi phương thức là một điều tĩnh hơn, bởi vì bạn phải có một tham chiếu đến một đối tượng kiểu bạn đang gọi phương thức, và một phương thức có cùng tên và kiểu chữ ký phải tồn tại trong kiểu đó , hoặc trình biên dịch sẽ phàn nàn. Điều thú vị là cuộc gọi thực sự là động, mặc dù điều này không rõ ràng đối với lập trình viên.

Ví dụ, hãy xem xét một lớp học như

class MyClass { 
    void doSomething() {} 
} 

class AnotherClass { 
    void someMethod() { 
     Object object = new Object(); 
     object.doSomething(); // compiler checks and complains that Object contains no such method. 

     // However, through an explicit cast, you can calm the compiler down, 
     // even though your program will crash at runtime 
     ((MyClass) object).doSomething(); // syntactically valid, yet incorrect 
    } 
} 

Trong tuy nhiên Objective-C, trình biên dịch chỉ đơn giản là vấn đề bạn một cảnh báo để thông qua một thông điệp tới một đối tượng mà nó nghĩ rằng đối tượng có thể không hiểu, nhưng bỏ qua nó không ngăn chương trình của bạn thực thi.

Trong khi điều này rất mạnh mẽ và linh hoạt, nó có thể dẫn đến lỗi khó tìm khi được sử dụng không chính xác do lỗi tham nhũng.

Được điều chỉnh từ bài viết here. Đồng thời xem bài viết this để biết thêm thông tin.

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