2011-10-26 28 views
6

Tôi muốn có một bản ghi (cấu trúc) với một 'đa hình' comportment. Nó sẽ có một số trường được sử dụng trong tất cả các trường hợp và tôi chỉ muốn sử dụng các trường khác khi tôi cần chúng. Tôi biết rằng tôi có thể thực hiện điều này bằng các phần khác nhau được khai báo trong hồ sơ. Tôi không biết nếu có thể vào thời điểm thiết kế, tôi chỉ có thể truy cập vào các yếu tố tôi cần. Để cụ thể hơn, hãy xem ví dụ dưới đâyDelphi - hồ sơ với các bộ phận khác nhau

program consapp; 

{$APPTYPE CONSOLE} 

uses 
    ExceptionLog, 
    SysUtils; 

type 
    a = record 
    b : integer; 
    case isEnabled : boolean of 
    true : (c:Integer); 
    false : (d:String[50]); 
    end; 


var test:a; 

begin 
test.b:=1; 
test.isEnabled := False; 
test.c := 3; //because isenabled is false, I want that the c element to be unavailable to the coder, and to access only the d element. 
Writeln(test.c); 
readln; 
end. 

Điều này có thể không?

Trả lời

7

Tất cả các trường biến thể trong một bản ghi biến thể có thể truy cập mọi lúc, bất kể giá trị của thẻ.

Để đạt được kiểm soát trợ năng bạn đang tìm kiếm, bạn sẽ cần sử dụng thuộc tính và có kiểm tra thời gian chạy để kiểm soát trợ năng.

type 
    TMyRecord = record 
    strict private 
    FIsEnabled: Boolean; 
    FInt: Integer; 
    FStr: string; 
    // ... declare the property getters and settings here 
    public 
    property IsEnabled: Boolean read FIsEnabled write FIsEnabled; 
    property Int: Integer read GetInt write SetInt; 
    property Str: string read GetString write SetString; 
    end; 
... 
function TMyRecord.GetInt: Integer; 
begin 
    if IsEnabled then 
    Result := FInt 
    else 
    raise EValueNotAvailable.Create('blah blah'); 
end; 
+2

+1. Tôi đã chắc chắn 80% đây là câu trả lời ... – RBA

+2

Điều này là hoàn toàn chính xác, nhưng trong trường hợp này, tôi muốn sử dụng một lớp thay vì một bản ghi. Nó sẽ cho phép thêm tính năng thừa kế, có ý nghĩa ở đây (ví dụ: thuộc tính IsEnable thường được xử lý ở cấp độ gốc và được chia sẻ giữa các trẻ em). –

-3

Ví dụ được cung cấp KHÔNG phải là bản ghi biến thể, nó bao gồm tất cả các trường mọi lúc.

Bản ghi biến thể thực có các biến thể chia sẻ cùng một bộ nhớ. Bạn chỉ cần sử dụng cú pháp "phân biệt chữ hoa chữ thường: DiscType of .....", không cần một trường riêng cho bạn biết biến thể nào đang hoạt động.

+0

Đây là một bản ghi biến thể. Các trường hợp làm cho nó như vậy. –

+0

Bạn đang nói về ** tuyệt đối ** biến, đó là một điều hoàn toàn khác nhau. David đúng, đây là một bản ghi biến thể. –

+0

Nó không bao gồm tất cả các trường, thay vào đó nó cung cấp quyền truy cập vào tất cả các phần sau khi 'case' _at cùng một time_ và tất cả chúng chia sẻ cùng một bộ nhớ. Vì vậy, nó tương tự như ** tuyệt đối ** vars, ngoại trừ: nó có cấu trúc hơn; bạn có biến thẻ; và, có thể, sự liên kết bộ nhớ hơi khác một chút –

3

Ngay cả khi tôi nghe rằng theo định nghĩa Pascal gốc của Niklaus Wirth, mọi thứ sẽ hoạt động như bạn mong đợi, tôi thấy không có hành vi nào như vậy ở Delphi, bắt đầu từ tổ tiên của nó, Turbo Pascal 2.0. Xem nhanh FreePascal cho thấy rằng its behaviour là giống nhau. Như đã nói trong Delphi documentation:

Bạn có thể đọc hoặc viết cho bất kỳ trường nào của bất kỳ biến thể nào bất kỳ lúc nào; nhưng nếu bạn viết vào một trường trong một biến thể và sau đó đến một trường trong một biến thể khác, bạn có thể ghi đè dữ liệu của riêng mình. Thẻ, nếu có, có chức năng như một trường bổ sung (thuộc loại ordinalType) trong phần không biến thể của bản ghi. "

Về ý định của bạn, theo như tôi đã hiểu, tôi sẽ sử dụng hai các lớp học khác nhau, loại

a = class 
     b : Integer 
    end; 

    aEnabled = class(a) 
     c: Integer 
    end; 

    aDisabled = class(a) 
     d: String //plus this way you can use long strings 
    end; 

Bằng cách này bạn có thể nhận được sự hỗ trợ từ Code Editor IDE ngay cả ở designtime. hữu ích hơn, tuy nhiên, là nó sẽ

nhiều dễ dàng hơn để sửa đổi và hỗ trợ sau.

Tuy nhiên, nếu bạn cần chuyển đổi nhanh chóng của bản ghi và các giá trị khả thi khi chạy, @David Heffernan's variant, để sử dụng các thuộc tính và có kiểm tra thời gian chạy, là hợp lý hơn.

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