2012-02-22 15 views
7

W jednej klasie bazowej jest chroniona procedura . Odziedziczyjąc tę ​​klasę, chcę ukryć tę procedurę przed użyciem z zewnątrz. Próbowałem przesłonić go z poziomu prywatnych, a nawet ściśle prywatnych sekcji, ale nadal można go wywoływać z zewnątrz. Klasa Oryginalna nie jest moja, więc nie mogę zmienić jej definicji.Jak ukryć chronioną procedurę obiektu?

Czy można ukryć tę procedurę w mojej odziedziczonej klasie? I jak?

type 
    TOriginal = class(TObject) 
    protected 
    procedure SomeProc; 
    end; 

    TNew = class(TOriginal) 
    strict private 
    procedure SomeProc; override; 
    end; 
+2

jeśli chcesz ukryć metodę klasy bazowej z potomek klasy potem trzeba zadeklarować je w sekcja prywatna; prywatne metody są widoczne tylko z własnej klasy; metody chronione są widoczne z klasy hislef i dziedziczonych klas i wreszcie metody publiczne lub opublikowane są widoczne dla wszystkich; opublikowane jest takie samo jak publiczne, ale te sekcje są używane przez Delphi IDE do tworzenia właściwości komponentów widocznych w inspektorze obiektów; – teran

+0

istnieją również dwa terminy "ukrywanie" i "nadpisywanie"; w twoim przykładzie musisz oznaczyć 'SameProc' w klasie bazowej jako' virtual'; a następnie redeclare go w odziedziczonej klasy i oznaczyć go jako "override" oznacza overriding; oznacza to, że jeśli utworzysz 'TNew' i przypiszesz jego instancję zmiennej' TOriginal' ('var orig: = TNew.Create()') i po tym wywołaniu orig.SomeProc zostanie wywołana implementacja TNew.SomeProc; jeśli nie zaznaczysz go jako "przesłonięcie", to orig.SomeProc jest równy 'TOriginal.SomeProc' również jest bezużyteczny, aby obniżyć widoczność metody, ponieważ zawsze możesz go upcast i wywołać – teran

+2

Co to jest zatrzymanie kodu przy użyciu klasy pochodnej od rzutowania odniesienia do odwołania do baz podstawowych lub przypisanie ich? Uzyskując dostęp do jakichkolwiek "ukrytych" metod? Tego, czego chcesz, nie można zrobić. Jeśli odczuwasz chęć, aby to uczynić, to wszystkie relacje dziedziczenia są złe. – mghie

Odpowiedz

11

Chronione metody są już ukryty z zewnątrz. (Głównie, patrz poniżej.) Nie można zmniejszyć widoczności członka klasy. Jeśli klasa bazowa zadeklarowała, że ​​metoda jest chroniona, wówczas wszyscy jej potomkowie mogą używać tej metody.


W Delphi, inny kod w tej samej jednostce jako klasy mogą uzyskać dostęp do chronionych członków tej klasy, nawet kod z niepowiązanych klas. Może się to czasem przydać, ale zwykle pozwala obejść inne niedociągnięcia w projektowaniu. Jeśli masz coś, co "naprawdę, naprawdę" powinno być chronione, możesz go chronić, a następnie nie będzie obowiązywać specjalna reguła dostępu do tego samego urządzenia.

+0

I używając 'Class Helpers' nadal można uzyskać dostęp do ściśle chronionych/prywatnych członków. –

+0

@LURD, o ile nie ma "pomocników jednostek", nie ma możliwości uzyskania dostępu do prywatnych członków. – OnTheFly

+0

Oryginalna klasa ('TOriginal') nie jest moją klasą, więc nie mogę jej po prostu zmienić. Patrząc dalej na oryginalną klasę, widzę, że 'SomeProc' jest w rzeczywistości * public * dalej w rodzinie, ale ta klasa, którą dziedziczę, przeniosła ją do' protected' co wyjaśnia, dlaczego jestem w stanie uzyskać do niego dostęp, . Więc kiedy coś zostanie ujawnione, nie może być nieodkryte? –

1

Raz wystawiony nie można go ukryć, ale można to zrobić na miejscu, gdzie jest nazywany w krańcowym sposób

TOriginalClass = class 
public 
    procedure Foo; 
end; 

TNewClass = class(TOriginalClass) 
public 
    procedure Foo; reintroduce; 
end; 

implementation 

procedure TNewClass.Foo; 
begin 
    Assert(False, 'Do not call Foo from this class'); 
    inherited Foo; 
end; 

var Obj: TNewClass; 
Obj := TNewClass.Create; 
Obj.Foo; // get assert message 

Will not get Assert error if declared as TOriginalClass 
var Obj: TOriginalClass; 
Obj := TNewClass.Create; 
Obj.Foo; // Never get the assert message 
+0

Dziękuję za odpowiedź i jestem trochę wyrozumiały, ale nie rozumiem, skąd pochodzi składnia podobna do C ... To nie wygląda na czysty kod Delphi ... –

+0

Chociaż rozumiem, że kod jest nadal trochę podejrzany, głównie obie klasy mają 'Foo' in * public *? –