2016-11-08 17 views
15

Tôi cố gắng kế thừa từ Tdictionary và bằng cách nào đó trình so sánh mặc định bị mất. Đây là những gì tôi làm trong bản chất:Delphi Tdictionary kế thừa

type 
    TinpVar = class 
    end; 
    TinputVars = class(Tdictionary<string,TinpVar>) 
    end; 
    TLVRvars = class(TinputVars) 
    constructor create; 
    end; 

constructor TLVRvars.create; 
begin 
    inherited; 
end; 

var LVRvars : TLVRvars; 

begin 
    LVRvars:=TLVRvars.create; 

Với công trình này tôi nhận được AV khi thêm cặp khóa/giá trị vào LVRvars. Cuối cùng tôi thấy rằng điều này có thể được ngăn chặn bằng cách thay đổi hàm tạo của lớp được kế thừa thành

constructor TLVRvars.create; 
begin 
    inherited create; 
end; 

Tôi không hiểu tại sao tôi phải làm điều đó. Mặc dù vấn đề của tôi đã được giải quyết, tôi vẫn muốn biết.

+0

Trước đây bạn có một nhà xây dựng không? – Dsm

Trả lời

20

Trong constructor của bạn

inherited; 

gọi các nhà xây dựng với danh sách tham số giống hệt nhau để xây dựng của bạn. Hàm tạo của bạn không có tham số và do đó, inherited gọi hàm tạo không làm gì trong TObject. Không chỉ có bạn bị mất so sánh của bạn, nhưng trường hợp của bạn là thiếu phần còn lại của các bước cần thiết trong xây dựng.

Khi bạn thay thế nó với

inherited Create; 

trình biên dịch thay vì thực hiện Nghị quyết phương pháp thông thường. Nó tìm kiếm danh sách tổ tiên của lớp và gọi phương thức đầu tiên mà nó có thể. Trong trường hợp đó là:

constructor Create(ACapacity: Integer = 0); overload; 

Do đó, cá thể của bạn được tạo đúng cách.

Các tài liệu là ở đây: http://docwiki.embarcadero.com/RADStudio/en/Methods#Inherited

trích đoạn chính là:

Nếu thừa hưởng được theo sau là tên của một thành viên, nó đại diện cho một phương pháp gọi bình thường

Khi được kế thừa không có số nhận dạng sau nó, nó tham chiếu s với phương thức được kế thừa có cùng tên với phương pháp kèm theo hoặc, nếu phương thức kèm theo là trình xử lý tin nhắn, cho trình xử lý tin nhắn được kế thừa cho thông báo tương tự . Trong trường hợp này, kế thừa không có tham số rõ ràng, nhưng chuyển sang phương thức được kế thừa cùng các tham số mà phương thức kèm theo được gọi. Ví dụ:

inherited; 

xảy ra thường xuyên trong việc triển khai các nhà thầu. Nó gọi phương thức khởi tạo được thừa kế với cùng các thông số đã được truyền cho hậu duệ .

Khá lạ phải không. Trên khuôn mặt của nó, có vẻ như đáng kinh ngạc rằng các phương pháp khác nhau được gọi là. Điểm mấu chốt là mặc dù số inherited đơn giản dẫn đến kết hợp chính xác các danh sách tham số. Và phương pháp của bạn không có tham số.

Mặt khác, inherited Create là cuộc gọi phương thức chuẩn. Trong trường hợp thứ hai, bạn kết thúc gọi một phương thức với một tham số, sử dụng giá trị mặc định cho tham số đó. Vì vậy, trong khi có vẻ như bạn đang gọi một constructor parameterless bạn không. Bạn đang chuyển một thông số, ACapacity và giá trị là 0.

+2

Làm nổi bật sự nguy hiểm của các tham số mặc định. Trong trường hợp này, những gì trông giống như mã tương đương chính xác: 'kế thừa;' (kết thúc) gọi ctor parameterless mặc định ** Tạo ** vs 'thừa kế Tạo;' mà * xuất hiện * để gọi một cách rõ ràng hàm ctor parameterless kế thừa ** Tạo * * nhưng trong thực tế, giải quyết cho một ctor với một tham số * mặc định *. Nắm bắt tốt. – Deltics

-2

Bộ so sánh là đối tượng cần được tạo. Nếu bạn không có hàm tạo nào trong lớp gốc của bạn, tôi sẽ mong đợi hàm tạo mặc định được tạo ra bởi vì bạn sẽ ngầm gọi cho hàm tạo kế thừa. Nếu bạn tạo constructor của riêng bạn, bạn nên luôn luôn gọi là Create thừa kế (theo ý kiến ​​của tôi) để cho phép tổ tiên làm công việc của nó - trong trường hợp này tạo bộ so sánh mặc định.

+2

Đây là phần lớn dấu ấn tôi sợ –