2014-05-04 14 views
6

Mam klasę TiffData, która zawiera abstrakcyjne metody ładowania i wyświetlania danych oraz wiele klas przodków, takich jak TTiffByte, TTiffAscii, TTiffShort, które definiują te metody.Jak odnieść się do klasy z stałej tablicy rekordów?

Mam również stałą tablicę lub rekordy, które pozwalają mi wyszukiwać informacje o typach w oparciu o typ danych zarejestrowany w IFD.

Czego nie mogę dowiedzieć się, jak zapisać powiązaną klasę dla każdego elementu tablicy.

type 
    TtiffType = record 
     name : string; 
     bytes : word; 
     data : class; { ? } 
     desc : string; 
    end; 

const 
TiffTypes : array[ 1 .. 18 ] of TTiffType = (

{01} (name: 'byte'; bytes : 1; data: TTiffByte;  { ? } 
     desc: '8-bit unsigned number.' ), 
{02} (name: 'ascii'; bytes : 1; data: TTiffAscii; { ? } 
     desc: '8 bit byte that contains a 7 bit ASCII code; the last byte must be NULL (binary zero)' ), 
{03} (name: 'short'; bytes : 2; data: TTiffShort; { ? } 
     desc: '16-bit (2-byte) unsigned integer.' ), 
... 

Co chciałbym zrobić, to trzymać referencję do klasy w tablicy:

value := TiffTypes[ fldType ].Data.Create; 

value.loadFromOffset(offset); 
Edit1.Text := value.getShortString; 

lub posiadać konstruktor w tablicy:

value := TiffTypes[ fldType ].data; 

value.loadFromFile(f, offset, count); 
InternalRepresentation := TTiffAscii(value.storage); 

Odpowiedz

3

Co trzeba to klasa meta.

type 
    TTiffDataClass = class of TiffData; 

Następnie można go używać tak:

TTiffType = record 
    name : string; 
    bytes : word; 
    data : TTiffDataClass; 
    desc : string; 
end; 

Jeśli masz potomkiem TiffData następnie można użyć. Na przykład:

TTiffByte= class(TiffData) 
end; 

To powinno działać:

{01} (name: 'byte'; bytes : 1; data: TTiffByte;  { ? } 
     desc: '8-bit unsigned number.' ), 

Jak Remi powiedział w swojej odpowiedzi, należy uważać z konstruktorów.

+0

PO stwierdził, że klasa bazowa to 'TiffData' więc należy odzwierciedlić w swojej odpowiedzi, że zamiast tworzących nowa fikcyjna nazwa. –

+0

@RemyLebeau Dzięki, zaktualizowałem odpowiedź. – Graymatter

7

od twojej klasy mają wspólną klasę bazową, TiffData, można użyć class of TiffData w rekordzie, np:

type 
    TtiffType = record 
    name : string; 
    bytes : word; 
    data : class of TiffData; // <-- here 
    desc : string; 
    end; 

Korzystanie Data.Create będzie wtedy działać zgodnie z oczekiwaniami, tak długo, jak konstruktor TiffData jest zadeklarowana jako virtual i każdej pochodnej klasy nadpisuje go.

+0

Dlaczego konstruktor musi być zadeklarowany jako wirtualny?Czy to nie zadziałałoby niezależnie? – Graymatter

+3

Nie. Powiedzmy, że "Dane" wskazuje na "TTiffByte". Wywołanie 'Data.Create' ** nie będzie ** wywoływać' TTiffByte.Create', jeśli 'TiffData.Create' nie jest wirtualny. Konstruktory wirtualne są bardzo ważne podczas tworzenia obiektów przy użyciu metaclasses. –

+0

Dowiedz się, dlaczego tak mówisz. Prawie nigdy nie wkładałem niczego do konstruktorów. W miarę możliwości używam AfterConstruction i BeforeDestruction. Powód, dla którego zmieniłem dawno temu, wynika właśnie z tego powodu. W tamtym czasie nie wiedziałem, co było powodem tego, że mój konstruktor nigdy nie był nazywany :). +1 dla ważnych informacji. – Graymatter

0

Dzięki Remi i Graymatter! Użyłem informacji z obu odpowiedzi, aby uzyskać następujący wynik. Niemal wszystko inne daje ostrzeżenia, błędy lub wyjątki czasu pracy.

Definiowanie wielu klas do zarządzania różnymi typami danych, wszystkich przodków TTiffData.

Type 

TTiffData = class(TObject) 
    constructor create; virtual; 
    procedure LoadFromIFD(var aValue; Count : LongWord ); virtual; abstract; 
end; 

TTiffShort = class(TTiffData) 
    constructor create; override; 
    procedure LoadFromIFD(var aValue; Count : LongWord ); override; 
end; 

TTiffAscii = class(TTiffData) 
    constructor create; override; 
    procedure LoadFromIFD(var aValue; Count : LongWord ); override; 
end; 

... 

Uwaga: użyłem „override” zamiast „wirtualny” w dzieci, aby zapobiec „metoda«*»ukrywa wirtualną metodę typu bazowego«TTiffData»” ostrzeżeń.

Tablica wygląda następująco:

type 
    TTiffDataClass = class of TTiffData; 

    TtiffType = record 
     name : string; 
     bytes : word; 
     data : TTiffDataClass; 
     desc : string; 
    end; 

const 


    TiffTypes : array[ 1 .. 18 ] of TTiffType = (
{01} (name: 'byte'; bytes : 1; data: TTiffShort; 
     desc: '8-bit unsigned number.' ), 
{02} (name: 'ascii'; bytes : 1; data: TTiffAscii; 
     desc: '8 bit byte that contains a 7 bit ASCII code; the last byte must be NULL (binary zero)' ), 

... 
); 

Zastosowanie:

{ Load } 
    Value := TiffTypes[ fldType ].data.Create; 

    if Indirect then begin 
     Value.LoadFromFile(f, Offset, Count); 
     end 

    else begin 
     ValueLoadFromIFD(Offset, Count); 
     end; 


    { Display } 
    aStringGrid.Cells[ 8, i ] := Value.ShortDisplay; 
+1

Ouch. Nie używaj 'override' do" zapobiegania ostrzeżeniom ". ** Proszę ** dowiedzieć się, co to znaczy i używać go odpowiednio. –

+0

Nie blokujesz ostrzeżeń, uniemożliwiasz wywoływanie nadpisujących metod. – deColaman

Powiązane problemy