2008-09-10 9 views
7

Cuộc gọi Delphi được kế thừa trên các thủ tục bị ghi đè nếu không có lệnh gọi rõ ràng trong mã tức là (thừa kế;), tôi có cấu trúc sau đây (từ siêu đến lớp con)Có gọi Delphi được thừa kế trên các thủ tục đã ghi đè nếu không có lệnh gọi rõ ràng

TForm >> TBaseForm >> TAnyOtherForm

Tất cả các hình thức trong dự án sẽ được bắt nguồn từ TBaseForm, vì điều này sẽ có tất cả các tiêu chuẩn thiết lập và phá hoại phần được sử dụng cho mọi hình thức (security, validation ect).

TBaseForm có onCreate và onDestroy các thủ tục với mã để làm điều này, nhưng nếu ai đó (tức là tôi) quên thêm kế thừa vào onCreate trên TAnyOtherForm thì Delphi có gọi nó cho tôi không? Tôi đã tìm thấy tài liệu tham khảo trên web nói rằng nó không phải là bắt buộc, nhưng hư không nói nếu nó được gọi là nếu nó được bỏ qua từ mã.

Ngoài ra, nếu nó được gọi là được kế thừa cho tôi, khi nào nó sẽ gọi nó?

Trả lời

17

Không, nếu bạn để cuộc gọi được kế thừa, nó sẽ không được gọi. Nếu không, nó sẽ không thể ghi đè lên một phương thức và hoàn toàn ommit phiên bản gốc của nó.

3

Cuộc gọi được kế thừa phải được thực hiện một cách rõ ràng. Nói chung không có ngôn ngữ nào tự động gọi hàm được kế thừa trong các tình huống tương đương (không bao gồm các hàm tạo lớp).

Thật dễ dàng để quên cuộc gọi được kế thừa trong một hàm tạo lớp. Trong tình huống như vậy nếu một lớp cơ sở cần khởi tạo bất kỳ dữ liệu nào mà bạn có vi phạm truy cập đang chờ xảy ra.

Có lẽ bạn có thể ghi đè DoCreate và DoDestory trong lớp TBaseForm của bạn để bạn có thể đảm bảo một số mã được thực thi bất kể việc triển khai các lớp con.

// interface 

TBaseForm = Class(TForm) 
... 
Protected 
    Procedure DoCreate(Sender : TObject); Override; 
End 

// implementation 

Procedure TBaseForm.DoCreate(Sender : TObject); 
Begin 
    // do work here 

    // let parent call the OnCreate property 
    Inherited DoCreate(Sender); 
End; 
3

Điều đáng nói là không được gọi kế thừa trong tiêu diệt bất kỳ đối tượng nào cũng có thể gây rò rỉ bộ nhớ. Có các công cụ có sẵn để kiểm tra điều này trong mã nguồn của bạn.

1

Mã được thừa kế không được gọi là ngầm, như những người khác đã chỉ ra. Bạn phải gọi nó một cách rõ ràng. Điều này mang lại cho bạn một số tính linh hoạt hữu ích. Ví dụ, bạn có thể muốn làm một số mã tiền xử lý trước mã kế thừa, sau đó thực hiện một số mã xử lý sau. Điều này có thể trông giống như:

procedure TMyCalcObject.SolveForX; 
begin 
    ResetCalcState; 
    inherited SolveForX; 
    PostProcessSolveForX; 
end; 
2

Thừa kế phải được gọi rõ ràng trong các đối tượng hậu duệ cũng như trong kế thừa hình thức trực quan. Nếu bạn sử dụng hoàn thành lớp thì nó sẽ tự động được thêm thừa kế nếu bạn gắn cờ định nghĩa là ghi đè (nhưng không được gắn kết lại). Nếu bạn đang sử dụng thừa kế biểu mẫu trực quan thì khi bạn thêm một trình xử lý sự kiện mới thông qua trình chỉnh sửa biểu mẫu thì nó cũng sẽ được thêm vào kế thừa.

0

Bạn phải gọi nó rõ ràng. Điều này cho phép rất nhiều tính linh hoạt, vì bạn có thể chọn tại điểm nào trong mã để gọi phương thức được kế thừa. Nhưng nó cũng là một nguồn lỗi lớn. Thật dễ dàng để quên gọi hàm được thừa hưởng và trình biên dịch không có cách nào để biết liệu bạn đã cố ý hay bạn chỉ quên.

Sẽ có một số loại chỉ thị "skip_inherited" để thông báo cho trình biên dịch rằng bạn không muốn gọi phương thức được kế thừa.

Trình biên dịch sau đó sẽ dễ dàng báo cáo lỗi nếu nó không tìm thấy "kế thừa" hoặc "skip_inherited". Điều đó có nghĩa là bạn đã quên. Nhưng tiếc là không ai trong CodeGear nghĩ về điều đó.