Đại biểu là gì? [đóng cửa]


152

Tôi bối rối rằng vai trò thực sự của một đại biểu là gì?

Tôi đã được hỏi câu hỏi này nhiều lần trong các cuộc phỏng vấn của tôi, nhưng tôi không nghĩ rằng những người phỏng vấn hài lòng với câu trả lời của tôi.

Bất cứ ai có thể cho tôi biết định nghĩa tốt nhất, trong một câu, với một ví dụ thực tế?


21
Vì tò mò, bạn đã trả lời những gì để chúng tôi có thể cho bạn biết làm thế nào bạn có thể sửa nó?
Anthony Forloney

6
Tôi thấy thú vị khi câu hỏi này đã được đóng lại nhưng có 126 câu hỏi và 65 người đánh dấu nó là một mục yêu thích. Có vẻ như ngay cả khi nó quá rộng, nó vẫn là một câu hỏi rất hay.
Giàu

Câu trả lời:


171

Tôi thích nghĩ về một đại biểu là "một con trỏ tới một hàm". Điều này quay trở lại C ngày, nhưng ý tưởng vẫn còn.

Ý tưởng là bạn cần có khả năng gọi một đoạn mã, nhưng đoạn mã mà bạn sẽ gọi không được biết cho đến khi chạy. Vì vậy, bạn sử dụng một "đại biểu" cho mục đích đó. Các đại biểu có ích cho những việc như xử lý sự kiện, và như vậy, nơi bạn làm những việc khác nhau dựa trên các sự kiện khác nhau, chẳng hạn.

Đây là một tài liệu tham khảo cho C # bạn có thể xem:

Ví dụ, trong C #, giả sử chúng tôi có một phép tính mà chúng tôi muốn thực hiện và chúng tôi muốn sử dụng một phương pháp tính toán khác mà chúng tôi không biết cho đến khi chạy. Vì vậy, chúng ta có thể có một vài phương pháp tính toán như thế này:

public static double CalcTotalMethod1(double amt)
{
    return amt * .014;
}

public static double CalcTotalMethod2(double amt)
{
    return amt * .056 + 42.43;
}

Chúng tôi có thể tuyên bố một chữ ký đại biểu như thế này:

public delegate double calcTotalDelegate(double amt);

Và sau đó chúng ta có thể khai báo một phương thức lấy đại biểu làm tham số như thế này:

public static double CalcMyTotal(double amt, calcTotalDelegate calcTotal)
{
    return calcTotal(amt);
}

Và chúng ta có thể gọi CalcMyTotalphương thức truyền trong phương thức ủy nhiệm mà chúng ta muốn sử dụng.

double tot1 = CalcMyTotal(100.34, CalcTotalMethod1);
double tot2 = CalcMyTotal(100.34, CalcTotalMethod2);
Console.WriteLine(tot1);
Console.WriteLine(tot2);

19
+1 cho cái gật đầu với con trỏ hàm đơn giản nhưng hiệu quả trong C.
Aiden Bell

3
Một câu hỏi liên quan đến câu trả lời của bạn. Làm thế nào nó thực sự khác với việc gọi một chức năng theo cách thông thường? Chỉ vì điều đó mà nó không được biết đến trong thời gian chạy?
Naveed

1
@NAVEED - tham khảo bản chỉnh sửa mới nhất của tôi, tôi đã bao gồm một ví dụ. Theo như cách gọi phương thức thực tế, nó không khác bất kỳ cuộc gọi phương thức bình thường nào trong ví dụ của tôi ở trên (calcTotal (amt) đang gọi đại biểu), nhưng sức mạnh của đại biểu là bạn có thể sử dụng chúng làm tham số, vv khi bạn muốn một phương pháp để có thể có hành vi khác nhau. Có nhiều thứ khác bạn cũng có thể sử dụng chúng, đây chỉ là một ví dụ đơn giản. Mong rằng sẽ giúp.
dcp

Nó không được biết đến trong thời gian chạy và là một hàm bị ràng buộc chứ không phải là một hàm miễn phí - việc gán một phương thức không tĩnh Foocho một đại biểu sẽ gọi this.Foo()chứ không phải là một hàm tĩnh như một con trỏ hàm sẽ làm (trong C, bạn thường có một void*tham số phụ chuyển thisđến con trỏ hàm)
Pete Kirkham

1
+1 cho ví dụ nhanh và hiệu quả thiết lập sự tương đồng với các con trỏ hàm trong C / C ++. Nhiều đánh giá cao!
G21

19

một đại biểu chỉ đơn giản là một con trỏ hàm.
chỉ cần đặt bạn chỉ định phương thức bạn muốn chạy đại biểu của mình. sau đó trong mã bạn có thể gọi phương thức đó thông qua Invoke.

một số mã để chứng minh (đã viết mã này từ bộ nhớ để cú pháp có thể bị tắt)

delegate void delMyDelegate(object o);

private void MethodToExecute1(object o)
{
    // do something with object
}

private void MethodToExecute2(object o)
{
    // do something else with object
}

private void DoSomethingToList(delMyDelegate methodToRun)
{
    foreach(object o in myList)
        methodToRun.Invoke(o);
}

public void ApplyMethodsToList()
{
    DoSomethingToList(MethodToExecute1);
    DoSomethingToList(MethodToExecute2);
}

16

Lấy từ đây

Q Đại biểu là gì?
A Khi một đối tượng nhận được yêu cầu, đối tượng có thể tự xử lý yêu cầu đó hoặc chuyển yêu cầu sang đối tượng thứ hai để thực hiện công việc. Nếu đối tượng quyết định chuyển yêu cầu trên, bạn nói rằng đối tượng đã chuyển tiếp trách nhiệm xử lý yêu cầu đến đối tượng thứ hai.

Hoặc, như một ví dụ giả dễ dàng: một cái gì đó gửi yêu cầu đến object1. object1 sau đó chuyển tiếp yêu cầu và chính nó tới object2 - đại biểu. object2 xử lý yêu cầu và thực hiện một số công việc. (lưu ý: liên kết ở trên cho ví dụ tốt)


Ví dụ đưa ra trong liên kết ở trên không nêu chính xác ủy quyền.
Hardik9850


4

Một đại biểu là một đối tượng có thể tham chiếu đến một phương thức. Vì vậy, khi chúng ta tạo một đại biểu, chúng ta đang tạo một đối tượng có thể chứa tham chiếu đến một phương thức. Hơn nữa, phương pháp có thể được gọi thông qua tài liệu tham khảo này. Do đó, một đại biểu có thể gọi phương thức mà nó đề cập đến. Ưu điểm chính của một đại biểu là nó cho phép chúng ta chỉ định một cuộc gọi đến một phương thức, nhưng phương thức thực sự được gọi được xác định trong thời gian chạy, không phải lúc biên dịch.

Đại biểu đơn giản

Declaration of delegate:
delegate-modifier delegate return-type delegate-name(parameters)
Implementation of delegate:
Delegate-name delegate-object=new Delegate-name(method of class)

http://ledgepacific.wordpress.com/2012/01/26/delegate/


2

Ở đây tôi sẽ giải thích các đại biểu, đại biểu phát đa hướng và cách sử dụng của họ .. Đại biểu là một loại chứa tham chiếu phương thức trong một đối tượng. Nó cũng được gọi là một con trỏ hàm an toàn loại. Chúng ta có thể nói một đại biểu là một loại xác định chữ ký phương thức.

Khi bạn khởi tạo một đại biểu, bạn có thể liên kết thể hiện của nó với bất kỳ phương thức nào với chữ ký tương thích. Bạn có thể gọi (hoặc gọi) phương thức thông qua thể hiện ủy nhiệm. Các đại biểu được sử dụng để truyền các phương thức làm đối số cho các phương thức khác. Trình xử lý sự kiện không có gì khác hơn là các phương thức được gọi thông qua các đại biểu. Ưu điểm của việc sử dụng đại biểu là, Đóng gói cuộc gọi của phương thức từ người gọi Việc sử dụng hiệu quả của đại biểu giúp cải thiện hiệu suất của ứng dụng Được sử dụng để gọi một phương thức không đồng bộ. Có một số tài sản của đại biểu là

Delegates are like C++ function pointers but are type safe.
Delegates allow methods to be passed as parameters.
Delegates can be used to define callback methods.
Delegates can be chained together; for example, multiple methods can be called on a single event.
Methods do not have to match the delegate signature exactly.

đại biểu công khai type_of_delegate ủy nhiệm_name () // Tuyên bố

You can use delegates without parameters or with parameter list
If you are referring to the method with some data type then the delegate which you are declaring should be in the same format. This is why it is referred to as type safe function pointer. Here I am giving an example with String.

Ví dụ sau đây cho thấy một hoạt động đại biểu:

    namespace MyDelegate
    {
        class Program
        {
            private delegate void Show(string s);


            // Create a method for a delegate.
            public static void MyDelegateMethod(string me

ssage)
        {
            System.Console.WriteLine(message);
        }

        static void Main(string[] args)
        {
            Show p = MyDelegateMethod;
            p("My Delegate");
            p.Invoke("My Delegate");
            System.Console.ReadLine();
        }
    }
}

Đại biểu Multicast là gì?

Nó là một đại biểu giữ tham chiếu của nhiều hơn một phương thức. Các đại biểu Multicast phải chỉ chứa các phương thức trả về void, nếu không có ngoại lệ thời gian chạy.

 delegate void MyMulticastDelegate(int i, string s);
 Class Class2
 {
  static void MyFirstDelegateMethod(int i, string s)
  {
    Console.WriteLine("My First Method");
  }

  static void MySecondDelegateMethod(int i, string s)
  {
    Console.WriteLine("My Second Method");
  }

  static void Main(string[] args)
  {
    MyMulticastDelegate Method= new MyMulticastDelegate(MyFirstDelegateMethod);
    Method+= new MyMulticastDelegate (MySecondDelegateMethod);
    Method(1,"Hi");             // Calling 2 Methodscalled
    Method-= new MyMulticastDelegate (MyFirstDelegateMethod);
    Method(2,"Hi");             //Only 2nd Method calling
  }
}

Ở đây, Delegate được thêm bằng toán tử + = và được loại bỏ bằng toán tử - =.

Các loại đại biểu được lấy từ lớp Delegate trong .NET Framework. Các loại đại biểu được niêm phong, họ không thể bắt nguồn. Bởi vì đại biểu khởi tạo là một đối tượng, nó có thể được truyền dưới dạng tham số hoặc được gán cho thuộc tính. Điều này cho phép một phương thức chấp nhận một đại biểu làm tham số và gọi cho đại biểu vào một thời gian sau. Điều này được gọi là một cuộc gọi lại không đồng bộ.


1

Có thể tìm thấy một lời giải thích tuyệt vời và triển khai thực tế về mẫu Đại biểu trong Lớp Chuyển tiếp Bộ sưu tập của Google (cũng là mẫu Trang trí).


1

Trong sự kiện giao tiếp người gửi không biết đối tượng nào sẽ xử lý sự kiện. Đại biểu là loại giữ tham chiếu của phương thức. Delegate có chữ ký và giữ tham chiếu đến phương thức khớp với chữ ký của nó để Delegate giống như kiểu con trỏ hàm an toàn.

button1.Click + = new System.EventHandler (button1_Click) System.EventHandler được khai báo là đại biểu ở đây Trong .net Sự kiện hoạt động trên khái niệm Delegate (như Nhấp chuột vào nút)

Delegate được sử dụng khi bạn không biết nên gọi mã nào trong thời gian chạy. Vì vậy, tại thời điểm đó, Delegate được sử dụng để xử lý các sự kiện

http://msdn.microsoft.com/en-us/l Library / ms173171 (v = vs.80) .aspx


1

Một đối tượng ủy nhiệm là một đối tượng mà một đối tượng khác tư vấn khi có điều gì đó xảy ra trong đối tượng đó. Ví dụ, người sửa chữa của bạn là đại biểu của bạn nếu có điều gì đó xảy ra với chiếc xe của bạn. bạn đến gặp người sửa chữa của bạn và yêu cầu anh ta sửa xe cho bạn (mặc dù một số người thích tự sửa xe, trong trường hợp đó, họ là đại biểu của chính họ cho chiếc xe của họ).


1

Một đại biểu là một đối tượng đại diện cho một con trỏ đến một chức năng. Tuy nhiên, nó không phải là một con trỏ hàm thông thường ở chỗ:

1) Hướng đối tượng

2) Là loại an toàn, tức là nó chỉ có thể trỏ đến một phương thức và bạn không thể đọc địa chỉ bộ nhớ thô mà nó đang trỏ đến

3) Được đánh máy mạnh mẽ. Nó chỉ có thể trỏ đến các phương thức phù hợp với chữ ký của nó.

4) Có thể trỏ đến nhiều hơn một phương thức cùng một lúc.


1

Đại biểu chủ yếu được sử dụng với các sự kiện.

Sự cần thiết là:

Bạn không muốn thực thi một đoạn mã tại thời điểm bạn chạy chương trình. Sau khi chạy chương trình, bạn muốn thực thi đoạn mã đó bất cứ khi nào sự kiện xảy ra.

Thí dụ :

  1. Ứng dụng Console - mã chỉ có thể được thực thi tại thời điểm bạn chạy chương trình. (Viết bên trong Phương thức chính)
  2. Ứng dụng Windows (lập trình giao diện người dùng) - mã có thể được thực thi khi nhấp vào nút sau khi chạy chương trình.

Đây là những gì họ nói, bạn không biết phương thức nào sẽ gọi vào lúc biên dịch. bạn biết nó chỉ trong thời gian chạy đó là khi nhấp vào nút.

Không có đại biểu, không thể lập trình giao diện người dùng. Bởi vì bạn đang thực thi mã bất cứ khi nào người dùng tạo các sự kiện đang nhấp vào nút, nhập vào hộp văn bản, chọn mục danh sách thả xuống, v.v.


0

Một đại biểu là một cái gì đó mà một nhiệm vụ đang được giao. Mục đích chính của ủy quyền là tách mã và cho phép linh hoạt hơn và tái sử dụng.

Trong lập trình và lập trình hướng đối tượng cụ thể, điều này có nghĩa là khi một phương thức được gọi để thực hiện một số công việc, nó chuyển công việc sang phương thức của một đối tượng khác mà nó có tham chiếu đến. Tham chiếu có thể trỏ đến bất kỳ đối tượng nào chúng ta muốn, miễn là đối tượng phù hợp với một bộ phương thức được xác định trước. Chúng tôi gọi nó là "lập trình cho một giao diện" (so với lập trình để thực hiện lớp cụ thể). Một giao diện về cơ bản là một mẫu chung và không có triển khai; nó chỉ đơn giản có nghĩa là một công thức, một tập hợp các phương pháp, điều kiện tiên quyết và hậu điều kiện (quy tắc).

Ví dụ đơn giản:

SomeInterface
{
   public void doSomething();
}


SomeImplementation implements SomeInterface
{
   public void doSomething()
   {
      System.err.println("Was it good for you?");
   }

}


SomeCaller
{
   public void doIt(SomeInterface someInterface)
   {
      someInterface.doSomething();
   }
}

Bây giờ bạn thấy tôi có thể sử dụng bất kỳ triển khai nào tôi muốn bất cứ lúc nào mà không cần thay đổi mã trong someCaller vì loại doIt()được truyền không cụ thể mà khá trừu tượng vì đó là giao diện. Trong thế giới Java, điều này thường được thể hiện trong mô hình dịch vụ nơi bạn gọi ra một dịch vụ (một đối tượng tự quảng cáo là dịch vụ thông qua một giao diện cụ thể) và sau đó dịch vụ gọi cho các đại biểu để giúp họ thực hiện công việc của mình. Các phương thức của dịch vụ được đặt tên là các tác vụ chi tiết thô (makePayment (), createdNewUser (), v.v.), trong khi bên trong nó thực hiện rất nhiều nếu nitty-gritty thông qua ủy quyền, với các kiểu của đại biểu là giao diện thay vì triển khai cụ thể.

SomeService
{
    SomeInterface someImplementation = ... // assign here
    SomeOtherInterface someOtherImplementation = ... // okay, let's add a second

    public void doSomeWork()
    {
         someImplementation.doSomething();
         someOtherImplementation.doSomethingElse();
    }
}

(NB: Cách triển khai được chỉ định nằm ngoài phạm vi của chuỗi này. Tra cứu đảo ngược kiểm soát và tiêm phụ thuộc.)


-2

Mặc dù không thực sự là "con trỏ hàm", một đại biểu có thể trông giống như đây là một ngôn ngữ động như PHP:



$func = 'foo';
$func();

function foo() {
    print 'foo';
}

hoặc trong JavaScript, bạn có thể làm một cái gì đó như:


var func = function(){ alert('foo!'); }
func();


2
Đây không phải là một ví dụ về phái đoàn. Trong ví dụ của bạn, bạn đang sử dụng cái được gọi là hàm biến, về cơ bản sẽ tìm một hàm có cùng tên với chuỗi mà biến đó đề cập đến. Xem các hàm biến: php.net/manual/en/fifts.variable-fifts.php
Aquarelle
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.