2010-12-11 28 views
8

Tôi vừa thử sử dụng Generics đầu tiên trong Delphi 2009 và bị lúng túng về cách sử dụng kiểu chung làm đầu vào cho hàm Hỗ trợ được sử dụng để xem một đối tượng có thực hiện hay không giao diện. Tôi đã tạo một mẫu nhỏ minh họa vấn đề.Sử dụng chức năng Hỗ trợ() với kiểu giao diện chung

Với chủng loại và hữu ích sau đây chức năng:

IMyInterface = interface 
['{60F37191-5B95-45BC-8C14-76633826889E}'] 
end; 

TMyObject = class(TInterfacedObject, IMyInterface) 
end; 

class function TFunctions.GetInterface<T>(myObject: TObject): T; 
var 
    specificInterface: T; 
begin 
    // This would compile, but looses the generic capability 
    //Supports(myObject, IMyInterface, specificInterface); 

    // This results in compile errors 
    Supports(myObject, T, specificInterface); 

    result := specificInterface; 
end; 

và đoạn mã sau:

class procedure TFunctions.Test; 
var 
    myObject: TMyObject; 
    myInterface: IMyInterface; 
begin 
    myObject := TMyObject.Create; 

    myInterface := GetInterface<IMyInterface>(myObject); 
end; 

tôi mong chờ không có vấn đề nhưng tôi nhận được lỗi thời gian biên dịch sau:

[Lỗi DCC] GenericExample.pas (37): E2029 '(' được mong đợi nhưng ',' tìm thấy [Lỗi DCC] Tạo icExample.pas (37): Dự báo E2014, nhưng biểu thức loại 'T' được tìm thấy

Tôi không chắc chắn trình biên dịch mong đợi tôi làm gì với T khi được sử dụng làm đối số thực tế cho hàm .

Tôi đã tìm kiếm xung quanh một chút và không thể giải quyết vấn đề này. Một phần của tôi nghi ngờ rằng nếu tôi có thể hiểu làm thế nào một tên giao diện được chuyển đổi sang IID: TGUID loại trong quá trình biên dịch, khi sử dụng một tên giao diện cụ thể, tôi có thể thực hiện một số headway, nhưng điều đó đã trốn tôi cũng.

Bất kỳ trợ giúp nào được đánh giá cao.

Trả lời

7

Không có gì đảm bảo rằng T có GUID được liên kết với nó, và không có phương tiện trong ngôn ngữ để viết một ràng buộc về tham số kiểu để đảm bảo.

Tên giao diện được chuyển thành GUID bởi trình biên dịch tìm kiếm tên trong bảng biểu tượng, cấu trúc dữ liệu của trình biên dịch đại diện cho giao diện và kiểm tra trường tương ứng cho GUID. Nhưng generics không giống như các mẫu C++; chúng cần được biên dịch và kiểm tra kiểu và được biết là hoạt động với bất kỳ tham số kiểu hợp lệ nào, và điều đó có nghĩa là ràng buộc tham số kiểu trong khai báo của nó.

Bạn có thể nhận GUID bằng RTTI (lần đầu tiên kiểm tra xem T có thực sự đại diện cho giao diện) với một cái gì đó như GetTypeData(TypeInfo(T))^.Guid và chuyển GUID đến Supports theo cách đó hay không.

+0

bạn có thể không áp dụng một ràng buộc rằng T phải là một số giao diện được chỉ định có GUID không? –

+1

Nếu nó cần phải là một số giao diện, sau đó mã không phải là chung chung. Hỗ trợ sẽ trả về một tham chiếu giao diện; trình biên dịch không thể biến đổi nó thành bất cứ thứ gì T là. –

+1

Barry, cảm ơn sự giúp đỡ của bạn. Phần lớn kinh nghiệm của tôi với lập trình chung là từ nền C++, và tôi mong rằng trình biên dịch sẽ biết nếu một giao diện có một Hướng dẫn giống như cách nó sẽ biết nếu tên giao diện được cung cấp trực tiếp. Nó có ý nghĩa hoàn hảo khi biết rằng các mẫu Generics <> C++. Cảm ơn một lần nữa. – Chad

3

Tại sao bạn thậm chí còn làm phiền?

Để sử dụng TFunctions.GetInterface này, bạn cần:

  • một giao diện
  • một tham chiếu đối tượng

Nếu bạn có những, sau đó bạn có thể chỉ cần gọi Hỗ trợ() trực tiếp:

intf := TFunctions.GetInterface<IMyInterface>(myObject); 

chính xác equivale nt tới:

Supports(IMyInterface, myObject, intf); 

Sử dụng generics ở đây là phí thời gian và công sức và thực sự đặt câu hỏi "Tại sao phải làm?".

Nó chỉ là làm cho những điều khó đọc hơn (như là như vậy thường là trường hợp với generics) và là cồng kềnh hơn để sử dụng.

Hỗ trợ() trả về một boolean thuận tiện để chỉ thành công/thất bại, mà bạn phải kiểm tra cho riêng sử dụng wrapper của bạn:

intf := TFunctions.GetInterface<IMyInterface>(myObject); 
    if Assigned(intf) then 
    // ... 

so:

if Supports(IMyInterface, myObject, intf) then 
    // We can use intf 

Khi tạo hàm bao quanh chức năng nó thường là trường hợp kết quả là một sự cải thiện trong tính ổn định hoặc khả năng sử dụng.

imho điều này không thành công trên cả hai tính và bạn chỉ nên gắn bó với chức năng Hỗ trợ().

+0

Ví dụ của tôi được chưng cất từ ​​bối cảnh thực tế, để hỏi một câu hỏi cụ thể và không minh họa cho thiết kế thực tế. – Chad

+2

Sau đó, bạn cần cung cấp ít nhất một số ngữ cảnh. Nếu không, nó giống như yêu cầu làm thế nào để có được từ A đến B mà không đề cập rằng bạn không thể lái xe và không có tiền cho một vé xe buýt. Nó có thể là ngay cả trong bối cảnh, những gì bạn đang làm không phải là cách tốt nhất/dễ nhất để đi về nó. Đó là tất cả tốt và tốt yêu cầu một câu hỏi cụ thể, nhưng nếu bạn muốn câu trả lời hữu ích sau đó nó không tốt ném ra bối cảnh quan trọng. – Deltics

+2

Tôi kính trọng không đồng ý. Chúc mừng. – Chad

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