Delphi 2009, trong số một số nội dung thú vị, cũng vừa có các phương thức ẩn danh. Tôi đã xem các ví dụ và các bài đăng trên blog về các phương thức ẩn danh, nhưng tôi chưa nhận được chúng. Ai đó có thể giải thích tại sao tôi nên vui mừng?Ai đó có thể giải thích các phương pháp ẩn danh cho tôi không?
Trả lời
Chỉ cần nghĩ mã callback điển hình khi bạn cần phải có dữ liệu có sẵn để gọi lại. Thông thường, dữ liệu này là cần thiết cho cuộc gọi lại chỉ, nhưng bạn phải nhảy qua một số vòng để có được nó ở đó mà không cần phải từ chức để thực hiện un-OOP thân thiện như biến toàn cục. Với các phương thức nặc danh, dữ liệu có thể ở nơi đó - bạn không cần phải mở rộng phạm vi của nó một cách không cần thiết hoặc sao chép nó vào một đối tượng trợ giúp nào đó. Chỉ cần viết mã gọi lại của bạn tại chỗ như một phương thức nặc danh và nó có thể truy cập và thao tác đầy đủ tất cả các biến cục bộ tại trang web nơi mà phương thức nặc danh được định nghĩa (không phải nơi nó được gọi!).
Có các khía cạnh khác của các phương pháp ẩn danh, rõ ràng nhất là thực tế là chúng, cũng: ẩn danh, nhưng đây là một thực tế khiến chúng "nhấp" cho tôi ...
Tôi đoán (Tôi không biết Delphi) điều này ngụ ý rằng bạn có thể tạo các chức năng như một loại đối tượng dữ liệu ngay bây giờ. Điều này có nghĩa là bạn có thể, ví dụ, chuyển các hàm thành các tham số cho các hàm khác. Ví dụ: Hàm sắp xếp có thể lấy hàm so sánh làm tham số, do đó linh hoạt hơn nhiều.
một phần. Delphi đã có con trỏ hàm. Nhưng bây giờ họ có thể được tạo ra một cách vô cùng. Xem bình luận của tôi. –
Vui lòng xem closures.
Chức năng ẩn danh Delphi là các đóng.
Chúng được tạo trong các chức năng khác và do đó có quyền truy cập vào phạm vi chức năng đó. Điều này thậm chí như vậy nếu chức năng vô định được gán cho tham số hàm được gọi sau khi hàm ban đầu được gọi. (Tôi sẽ tạo một ví dụ trong giây lát).
type
TAnonFunc = reference to procedure;
TForm2 = class(TForm)
Memo1: TMemo;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
private
F1 : TAnonFunc;
F2 : TAnonFunc;
end;
procedure TForm2.Button1Click(Sender: TObject);
var
a : Integer;
begin
a := 1;
F1 := procedure
begin
a := a + 1;
end;
F2 := procedure
begin
Memo1.Lines.Add(IntToStr(a));
end;
end;
Phương thức trên chỉ định hai chức năng ẩn danh cho trường F1 và F2. Đầu tiên tăng biến cục bộ và biến thứ hai hiển thị giá trị của biến.
procedure TForm2.Button2Click(Sender: TObject);
begin
F1;
end;
procedure TForm2.Button3Click(Sender: TObject);
begin
F2;
end;
Bây giờ bạn có thể gọi cả hai chức năng và chúng truy cập giống nhau. Vì vậy, gọi F1 hai lần và F2 một lần cho thấy một 3. Tất nhiên đây là một ví dụ đơn giản. Nhưng nó có thể được mở rộng sang mã hữu ích hơn.
Trong môi trường đa luồng, các chức năng ẩn danh có thể được sử dụng trong một cuộc gọi đến Đồng bộ hóa, giúp loại bỏ sự cần thiết của vô số phương pháp.
ok, nhưng tôi vẫn không vui! Generics Tôi rất vui vì tôi có thể thấy 100 địa điểm tôi có thể sử dụng chúng. Phương pháp vô danh vẫn để tôi lạnh. – Steve
Bạn không cần phải vui mừng, bạn sẽ tìm thấy một cách sử dụng cho chúng ;-). –
Có lẽ vui mừng không phải là từ đúng, nhưng điều tôi ngụ ý là tôi không thể nghĩ ra một ví dụ thế giới thực (chưa), nơi tôi muốn nói "Vâng, đó chỉ là phương pháp Anaoymous là" – Steve
Phương pháp ẩn danh rất hữu ích trong lập trình hàm, nhưng chúng cũng có thể giúp bạn viết một mã nhỏ gọn hơn trong lập trình có cấu trúc. Threading, ví dụ: http://blogs.codegear.com/abauer/2008/09/08/38868
Một trường hợp sử dụng cho 'phấn khích' của bạn :): http://delphi.fosdal.com/2008/08/anonymous-methods-when-to-use-them.html
Có thể ví dụ này có thể được một số giá trị cho bạn. Ở đây tôi sẽ thực hiện một danh sách hiển thị có thể phóng to để vẽ trên một TCanvas mà không khai báo các loại lớp hiển thị khác nhau. Nó cũng làm cho việc sử dụng Generics nặng nề. Giả sử chúng ta có một TForm với một TPaintBox và một TTrackBar trên nó ...
type
TDisplayProc = TProc<TCanvas>;
type
TFrmExample3 = class(TForm)
pbxMain: TPaintBox;
trkZoom: TTrackBar;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure pbxMainClick(Sender: TObject);
procedure pbxMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
procedure pbxMainPaint(Sender: TObject);
procedure trkZoomChange(Sender: TObject);
private
FDisplayList: TList<TDisplayProc>;
FMouseX: Integer;
FMouseY: Integer;
FZoom: Extended;
procedure SetZoom(const Value: Extended);
protected
procedure CreateCircle(X, Y: Integer);
procedure CreateRectangle(X, Y: Integer);
function MakeRect(X, Y, R: Integer): TRect;
public
property Zoom: Extended read FZoom write SetZoom;
end;
implementation
{$R *.dfm}
procedure TFrmExample3.PaintBox1Paint(Sender: TObject);
var
displayProc: TDisplayProc;
begin
for displayProc in FDisplayList do
displayProc((Sender as TPaintBox).Canvas);
end;
procedure TFrmExample3.CreateCircle(X, Y: Integer);
begin
FDisplayList.Add(
procedure (Canvas: TCanvas)
begin
Canvas.Brush.Color := clYellow;
Canvas.Ellipse(MakeRect(X, Y, 20));
end
);
end;
procedure TFrmExample3.CreateRectangle(X, Y: Integer);
begin
FDisplayList.Add(
procedure (Canvas: TCanvas)
begin
Canvas.Brush.Color := clBlue;
Canvas.FillRect(MakeRect(X, Y, 20));
end
);
end;
procedure TFrmExample3.FormCreate(Sender: TObject);
begin
FDisplayList := TList<TDisplayProc>.Create;
end;
procedure TFrmExample3.FormDestroy(Sender: TObject);
begin
FreeAndNil(FDisplayList);
end;
function TFrmExample3.MakeRect(X, Y, R: Integer): TRect;
begin
Result := Rect(Round(Zoom*(X - R)), Round(Zoom*(Y - R)), Round(Zoom*(X + R)), Round(Zoom*(Y + R)));
end;
procedure TFrmExample3.pbxMainClick(Sender: TObject);
begin
case Random(2) of
0: CreateRectangle(Round(FMouseX/Zoom), Round(FMouseY/Zoom));
1: CreateCircle(Round(FMouseX/Zoom), Round(FMouseY/Zoom));
end;
pbxMain.Invalidate;
end;
procedure TFrmExample3.pbxMainMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
FMouseX := X;
FMouseY := Y;
end;
procedure TFrmExample4.SetZoom(const Value: Extended);
begin
FZoom := Value;
trkZoom.Position := Round(2*(FZoom - 1));
end;
procedure TFrmExample4.trkZoomChange(Sender: TObject);
begin
Zoom := 0.5*(Sender as TTrackBar).Position + 1;
pbxMain.Invalidate;
end;
Mọi người đã cung cấp mã, vì vậy tôi sẽ liệt kê một số nơi chúng có thể hữu ích.
Giả sử bạn có một số mã GUI. Thông thường, đối với một cái gì đó giống như trình xử lý onclick của nút, bạn phải cung cấp một hàm sẽ được gọi khi nút đó được nhấp. Tuy nhiên, chúng ta hãy nói rằng tất cả các chức năng đó phải làm là một cái gì đó đơn giản như bật lên một hộp tin nhắn hoặc thiết lập một lĩnh vực một nơi nào đó. Giả sử bạn có hàng tá các nút này trong suốt mã của bạn. Nếu không có hàm ẩn danh, bạn sẽ phải có rất nhiều hàm gọi là "OnButton1Click", "OnExitButtonClick", v.v., có khả năng sẽ làm lộn xộn mã của bạn ... hoặc bạn có thể tạo các hàm ẩn danh ngay lập tức đính kèm với những sự kiện này và bạn không không phải lo lắng về họ nữa.
Sử dụng khác là lập trình chức năng. Giả sử bạn có danh sách các số. Bạn muốn lấy lại chỉ những con số chia hết cho ba.Có khả năng một hàm được gọi là filter
, hàm này trả về một boolean và một danh sách và trả về một danh sách mới chỉ chứa các phần tử trong danh sách đầu tiên, khi được truyền cho hàm, trả về True. Ví dụ:
filter(isOdd, [1, 2, 3, 5, 6, 9, 10]) --> [1, 3, 5, 9]
Nó muốn được gây phiền nhiễu để bị buộc phải định nghĩa một hàm "isDivisibleByThree", sau đó vượt qua nó để lọc, vì vậy khác sử dụng cho các chức năng ẩn danh ở đây sẽ được chỉ một cách nhanh chóng tạo ra một chức năng bạn sẽ không cần bất cứ nơi nào khác và vượt qua nó để lọc.
tôi trả lời câu hỏi của riêng tôi, nhưng tôi tìm thấy một lời giải thích tốt về phương pháp vô danh ở đây Can your programming language do this?
+1 IMO Câu trả lời của bạn là câu trả lời hay nhất. – Sam
- 1. Ai đó có thể giải thích cho tôi phương pháp GetCardinality này đang làm gì không?
- 2. Ai đó có thể giải thích ASP.NET MVC cho tôi?
- 3. Ai đó có thể giải thích cho tôi này `StaleDataException`
- 4. Ai đó có thể giải thích attr?
- 5. Ai đó có thể giải thích các calipers quay cho tôi không?
- 6. Ai có thể giải thích cho tôi phương pháp xoay javax này không?
- 7. Ai đó có thể giải thích MustOverride?
- 8. Ai đó có thể giải thích cú pháp khai báo phương pháp C Mục tiêu
- 9. Ai đó có thể giải thích cho tôi về NaN trong Ruby không?
- 10. Ai đó có thể giải thích mẫu javascript này được sử dụng trong các plugin Twitter Bootstrap cho tôi không?
- 11. Có thể ai đó giải thích __declspec (trần truồng) không?
- 12. Ai đó có thể giải thích các hoạt động bitwise ARM cho tôi?
- 13. Ai đó có thể giải thích lớp << tự cho tôi không?
- 14. PHP - Ai đó có thể giải thích chức năng pfsockopen cho tôi không? (Socket dai dẳng)
- 15. Ai đó có thể giải thích cho tôi khi sử dụng MapMaker hoặc WeakHashMaps không?
- 16. Ai đó có thể cho tôi giải thích tốt về hành vi 'gửi' cho các ổ cắm không chặn không?
- 17. Có thể ai đó vui lòng giải thích các truy vấn phương tiện CSS?
- 18. Ai đó có thể giải thích DBCC DROPCLEANBUFFERS?
- 19. Ai đó có thể giải thích mạng nơron nhân tạo?
- 20. Ai đó có thể giải thích về Microsoft Unity?
- 21. Ai đó có thể Giải thích mã java này
- 22. Ai đó có thể giải thích sự tấn công SQL injection này cho tôi?
- 23. Ai đó có thể giải thích eclipse.p2.profile
- 24. Ai đó có thể giải thích hành vi của "conj"?
- 25. Ai đó có thể giải thích dòng mã này?
- 26. C# Ai đó có thể giải thích logic boolean này
- 27. Ai đó có thể giải thích thuật toán backpropagation cho tôi?
- 28. Ai đó có thể giải thích sự bù đắp cho tôi?
- 29. Ai đó có thể giải thích hành vi mô đun Integer này cho tôi trong Haskell?
- 30. ai đó có thể vui lòng giải thích cho tôi @MapsId trong chế độ ngủ đông?
Đây là một bình luận khiến tôi trở thành 'AHA'. Không vui mừng 100% nhưng ít nhất tôi có thể thấy một thế giới thực sử dụng cho nó bây giờ. – Steve