2009-11-21 39 views
5

Tôi có một lớp của tôi, cho phép gọi nó là TMyObject, sẽ trả về bản sao sửa đổi của chính nó. Vì vậy, một trong các chức năng của nó sẽ trả về một đối tượng cùng loại với chính nó:Tôi có thể tạo một đối tượng cùng loại với chính nó không?

function TMyObject.TrimEnds: TMyObject; 
begin 
    Result:= TMyObject.Create; 
    Result.DoStuff; 
edn; 

Tôi có thể làm điều đó không? Có phải tôi đang làm gì không?

Ý tôi là, tôi đã thử nó và trình biên dịch cho phép tôi làm điều đó, nhưng tôi tự hỏi liệu sẽ có thời gian dài/ẩn hiệu ứng tiêu cực.

Bất kỳ suy nghĩ nào cũng sẽ được đánh giá cao. Cảm ơn.


Chỉnh sửa: Bản sao mới sửa đổi một chút sẽ được lưu vào đĩa. Đó là một loại 'Lưu thành ...'. Cách hoạt động: Đối tượng gốc tạo bản sao của chính nó, hướng dẫn bản sao này thực hiện một số thay đổi và lưu vào đĩa. Sau đó bản gốc giải phóng bản sao. Bằng cách này tôi giữ đối tượng gốc trong bộ nhớ không thay đổi nhưng tôi có một phiên bản sửa đổi này vào đĩa.

Bạn có thể nghĩ rằng đối tượng của tôi có ảnh. Những gì tôi cần là một chức năng trả về một bản sao sửa đổi của bức ảnh.

Trả lời

5

nhưng tôi tự hỏi liệu sẽ có thời gian dài thời gian/hiệu ứng tiêu cực ẩn.

Tôi không thấy bất kỳ điều gì và tôi đã từng làm điều này với danh sách được liên kết của riêng mình và không bao giờ gặp bất kỳ sự cố nào. Tôi nghĩ nó khá giống với việc tạo một thể hiện ở bất kỳ nơi nào khác.

+0

vĩ đại. Rất cám ơn tất cả. – Ampere

+0

Đảm bảo bạn giải phóng tài nguyên. Nếu không, các đối tượng của bạn vẫn còn trong bộ nhớ và không bao giờ được giải phóng. Vâng, về chương trình chấm dứt nó được. – Scoregraphic

1

hoàn toàn không có gì sai với những gì bạn đã viết. bạn chỉ đơn giản là quay trở lại một đối tượng và điều này là hoàn toàn hợp lệ, nó có thể là bất kỳ đối tượng nào khác của bất kỳ loại nào khác.

2

Tôi đoán bạn nói đúng, đoạn mã này có vẻ sai với tôi. Bạn luôn phải nêu rõ ai là người chịu trách nhiệm trả miễn phí đối tượng bạn quay trở lại. Trong hầu hết các trường hợp, đối tượng này sẽ không được giải phóng.

Một cách tiếp cận tốt hơn là thường để người gọi tạo đối tượng, chuyển nó vào phương thức của bạn (bạn chỉ cần một thủ tục sau đó) để sửa đổi nó.

Tôi tò mò muốn biết lý do bạn muốn trả lại "phiên bản được sửa đổi một chút" của đối tượng của bạn. Nghe có vẻ phản trực giác với tôi ...

+0

Vui lòng xem bài đăng gốc của tôi. Tôi đã thêm nhiều giải thích hơn. – Ampere

2

Như những người khác đã nói, không có gì sai với điều đó nhưng có thể có những cách tốt hơn.

Biến thể 1: Thay đổi thành phương thức lớp và đặt tên có ý nghĩa.

class function TMyObject.CreateSpecialized: TMyObject; 
begin 
    Result := TMyObject.Create; 
    //initialize Result 
end; 

anObj := TMyObject.CreateSpecialized; 

Biến thể 2: Sử dụng hàm tạo. Bạn có thể có nhiều hàm tạo trong một lớp.

constructor TMyObject.CreateSpecialized; 
begin 
    Create; // make sure everything is initialized correctly 
    // now do custom initialization 
end; 

anObj := TMyObject.CreateSpecialized; 

Cách sử dụng giống nhau trong cả hai ví dụ nhưng trong trường hợp thứ hai, ý định của bạn rõ ràng hơn với người đọc ngẫu nhiên.

Nếu bạn muốn lấy một đối tượng và tạo một đối tượng khác dựa trên các trường của đối tượng đầu tiên, hãy sử dụng hàm tạo với tham số.

constructor TMyObject.CreateSpecialized(obj: TMyObject); 
begin 
    Create; 
    intField := obj.IntField * 2; 
end; 

anObj := TMyObject.CreateSpecialized(otherObj); 
+0

+1 cho phương thức lớp – RRUZ

+0

Có một số truyền thống gọi ví dụ cuối cùng của bạn là "constructor sao chép" –

+0

@PA: Không, với tư cách là một nhà xây dựng sao chép sẽ tạo một bản sao * giống hệt * chứ không phải một bản sao bị thay đổi. Sao chép các nhà xây dựng không được sử dụng nhiều trong Delphi. Vì tất cả các đối tượng chỉ được truy cập thông qua các tham chiếu nên hiếm khi có nhu cầu đối với chúng. – mghie

2

Nếu bạn có một lớp mới có nguồn gốc từ TMyObject như TMyOtherObject = class(TMyObject), các TrimEnds chức năng sẽ vẫn trả về một TMyObject thay vì một TMyOtherObject như người ta có thể mong đợi.

Bạn có thể khắc phục điều này bằng cách sử dụng chương trình này:

TMyObjectClass = class of TMyObject; 

function TMyObject.TrimEnds: TMyObject; 
begin 
    Result:= TMyObjectClass(ClassType).Create; 
    Result.DoStuff; 
end; 
+0

Điều đó sẽ không yêu cầu Tạo thành ảo? – gabr

+0

@gabr: Chỉ khi lớp dẫn xuất có tạo riêng. Trong trường hợp đó, cơ sở Create phải là ảo và bắt nguồn phải ghi đè lên nó. Việc sử dụng ClassType chỉ đảm bảo rằng lớp chính xác được khởi tạo - người dùng phải cẩn thận khi tạo ra đúng Create. –

+0

Hàm khởi tạo cần được khai báo ảo, nếu không mã trình xây dựng sẽ không được thực thi: http://stackoverflow.com/questions/791069/ – mjn

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