2012-12-05 5 views
6

Mam klasy nadrzędnej z jednym ważnym streszczenie procedury, która mam przeciążenia w wielu klasach potomnych jako przykładowy kod poniżej:Jak mogę przeciążać funkcję wirtualną wprowadzoną w klasie nadrzędnej?

TCParent = Class 
private 
public 
procedure SaveConfig; virtual; abstract; 

end; 

TCChild = Class(TCParent) 
private 
public 
procedure SaveConfig; override; 
end; 

Teraz nie muszę (przeciążenie) tę procedurę z inną procedurą SaveConfig które będą akceptuj parametry, ale nie chcę wprowadzać dużych zmian w klasie nadrzędnej, które mogą wymagać przejścia i wprowadzania zmian we wszystkich innych klasach potomnych.

Czy istnieje sposób mogę przeciążać SaveConfig w tej konkretnej klasy dziecka bez większych zmian do klasy dominującej i innych klas podrzędnych, które dziedziczą z niego?

+3

Dlaczego ten nowy "SaveConfig" musi mieć tę samą nazwę? Dlaczego nie nazwać tego czymś innym? – awmross

+1

@awmross Bo gdy chcę dodać przeciążenie do 'TStream.Seek' że bierze' Int64' offset. Nie mylić pytania z przykładem. –

Odpowiedz

9

Można użyć reintroduce aby dodać nową metodę przeciążony. Zauważ, że wymagana jest kolejność reintroduce; overload; w klasie potomnej; jeśli je odwrócisz, kod się nie skompiluje.

TCParent = Class 
private 
public 
procedure SaveConfig; virtual; abstract; 
end; 

TCChild = Class(TCParent) 
private 
public 
procedure SaveConfig; overload; override; 
procedure SaveConfig(const FileName: string); reintroduce; overload; 
end; 

(Testowany w Delphi 7, więc powinien działać w nim i wszystkich nowszych wersjach).

+0

Niestety używam Delphi 7 :(Więc kiedy próbowałem skompilować powyższy kod mam błąd: [Błąd] uClassChild.pas (13): Deklarację różni „SaveConfig” z poprzedniej deklaracji wskazując na linii Procedura SaveConfig (const NazwaPliku: ciąg); ponowne wprowadzenie; przesłonięcie; – MChan

+0

Nie masz szczęścia, AFAIK, nie ma sposobu, aby zrobić to samo w D7 (dlatego wprowadzono nową dyrektywę 'reintroduce' ) –

+1

Ale reintrodukcja istnieje w Delphi 7, po prostu nie kompiluje się z powyższą definicją proc ... aby być bardziej szczegółowym, D7 nie akceptuje ponownego wprowadzenia w tej konkretnej definicji, ale zaakceptuje ją normalnie w innej definicji – MChan

4

Ponieważ nie chcą wprowadzać zmiany w innych zstępnych, chciałbym zaproponować dodanie opcjonalnego pole do rodzica klasa do przechowywania parametrów, wtedy każdy potomek, który chce użyć parametrów, może z nich korzystać. W ten sposób nie trzeba zmieniać podpisu nadpisanego SaveConfig(). Na przykład:

type 
    TCParent = class 
    protected 
    SaveConfigParams: TStrings; // or whatever... 
    public 
    procedure SaveConfig; overload; virtual; abstract; 
    procedure SaveConfig(Params: TStrings); overload; 
    end; 

procedure TCParent.SaveConfig(Params: TStrings); 
begin 
    SaveConfigParams := Params; 
    try 
    SaveConfig; 
    finally 
    SaveConfigParams := nil; 
    end; 
end; 

.

type 
    TCChild = class(TCParent) 
    public 
    procedure SaveConfig; override; 
    end; 

procedure TCChild.SaveConfig; 
begin 
    if SaveConfigParams <> nil then 
    begin 
    // do something that uses the parameters... 
    end else begin 
    // do something else... 
    end; 
end; 

.

type 
    TCChild2 = class(TCParent) 
    public 
    procedure SaveConfig; override; 
    end; 

procedure TCChild2.SaveConfig; 
begin 
    // do something, ignoring the SaveConfigParams... 
end; 
+0

Dziękuję za twoją pomoc, ale nie jestem pewna, czy zrozumiałam tę część wyraźnie .... więc po to, aby upewnić się, że rozumiem cię poprawnie ... masz na myśli, że w klasie dziecka w zależności od SaveConfigParams w instrukcji IF Wykonam kod pod instrukcją IF .... jeśli to prawda, to jaka jest potrzeba sparametryzowanej procedury SaveConfig w klasie nadrzędnej? – MChan

+1

Klasa podrzędna może opcjonalnie sprawdzić, czy parametry zostały określone w razie potrzeby, a jeśli zostaną wykryte, to odpowiednio dostosuj jej zachowanie, w przeciwnym razie po prostu zignoruj ​​je i wykonaj inne czynności. To jest cały punkt - parametry są opcjonalne, ale przechowywane w rodzicu, gdzie każde dziecko może wyglądać, jeśli jest potrzebne. To jest to, o co prosiłeś - do obsługi parametrów bez konieczności wprowadzania zmian wszędzie. Ostatecznie, lepszym wyborem jest po prostu odgryzienie kuli i zmiana 'SaveConfig()', aby nadać jej opcjonalne parametry wejściowe, a następnie dokonać tej zmiany u każdego dziecka. Twój kod będzie dla niego czystszy. –

Powiązane problemy