2009-08-04 6 views
5

W klasie bazowej mam tę właściwość:Dlaczego nie mogę dodać zestawu accessor do właściwości overriden?

public virtual string Text 
{ 
    get { return text; } 
} 

Chcę przesłonić które i powrócić inny tekst, ale chciałbym również, aby móc ustawić tekst, więc zrobiłem to:

public override string Text 
{ 
    get { return differentText; } 
    set { differentText = value; } 
} 

To jednak nie działa. Dostaję czerwoną falistą pod set mówiąc, że nie mogę przesłonić, ponieważ nie ma ustawionego akcesora. Dlaczego to nieprawdaż? Co powinienem zrobić?

+0

Chciałbym zrobić dokładnie to samo. Powinno być możliwe. –

+0

Jest to możliwe, ale wymaga "klasy średniej". Poza tym prawdopodobnie nie jest to dobry pomysł w wielu sytuacjach, ale są pewne wyjątki, na przykład w przypadku nadpisywania właściwości abstrakcyjnych. Podstawa: 'public abstract string Text {get; } '. Środek (dziedziczy bazę): 'chroniony wewnętrzny tekst ciągu;' 'publiczny blokowany tekst zastępujący Tekst {get {return text; }} '. Dziecko (dziedziczy po środku): 'public new string Tekst {get {return text; } set {text = value; }} '. Chroniony modyfikator wewnętrzny i uszczelnione zabezpieczenie zapewniają hermetyzację poza podzespołem. – AnorZaken

+0

@AnorZaken: To nie jest przesłonięcie, to cień. Nie wymaga też klasy "środkowej". – Guffa

Odpowiedz

3

W swoim drugim bloku kodu tworzonego metodę nastawioną publicznego, ale słowo „override” w deklaracji kompilator szuka metody z tym samym podpisem w klasie bazowej. Ponieważ nie może znaleźć tej metody, nie pozwoli ci utworzyć swojego zestawu.

Jak ArsenMkrt mówi, że możesz zmienić swoją podstawową deklarację, aby zawierała chroniony zestaw. To pozwoli ci to zmienić, ale ponieważ nadal nie będziesz w stanie zmienić podpisu, nie możesz wypromować tej metody na publiczną w swojej podklasie, więc kod, który wysłałeś, nadal nie będzie działał.

Zamiast tego należy dodać publiczną metodę zestawu wirtualnego do swojej klasy bazowej, która niczego nie robi (lub nawet zgłasza wyjątek, jeśli spróbujesz ją wywołać), ale jest to sprzeczne z oczekiwaniami użytkownika klasy zachowanie się tak, jeśli to zrobić (i nie polecam go), upewnij się, że jest tak dobrze udokumentowane, że użytkownik nie może zabraknąć go:

///<summary> 
///Get the Text value of the object 
///NOTE: Setting the value is not supported by this class but may be supported by child classes 
///</summary> 
public virtual string Text 
{ 
    get { return text; } 
    set { } 
} 

//using the class 

BaseClass.Text = "Wibble"; 
if (BaseClass.Text == "Wibble") 
{ 
    //Won't get here (unless the default value is "Wibble") 
} 

przeciwnym razie zadeklarować jako osobny zestaw metody w twoja klasa dziecka:

public override string Text 
{ 
    get { return differentText; } 
} 

public void SetText(string value) 
{ 
    differentText = value; 
} 
+0

Nie podoba mi się to, ale myślę, że będę musiał zrobić coś na wzór oddzielnej metody SetText czy coś takiego ... dzięki :) – Svish

+0

Cóż, może również być problemem architektonicznym. Dlaczego użytkownik nie może ustawić wartości tekstowej w klasie bazowej? Czy to * naprawdę * ta sama właściwość w obu klasach? Wydaje się, że zwykle wymaga się takiego wzoru. –

+0

Cóż, jest to szereg różnych klas parametrów, które przechowuje różne rodzaje wartości. I chciałbym, aby wszyscy oni byli w stanie przedstawić się jako wartość tekstowa, którą użytkownik może przeczytać (na przykład do drukowania). Ale nie chcę, aby wszystkie parametry były ustawione przez tekst (parsowanie jest o wiele bardziej irytujące niż drukowanie). Na przykład parametr daty chcę wydrukować datę, ale nie trzeba ustawiać daty za pomocą tekstu, ponieważ ustawienie zostanie wykonane za pomocą datepika. – Svish

3
public virtual string Text 
{ 
    get { return text; } 
    protected set {} 
} 

baza zmiana klasy nieruchomość tak, staramy się zastąpić ustawioną metodę, która nie istnieje

+0

Nie można przesłonić chronionego setera jako ustawiciela publicznego w klasie potomnej. – Guffa

+0

hmm, zgadzam się .... :) –

2

To jest problem, bo się rozpadasz g enkapsulacji. Nie możesz przesłonić czegoś i uczynić go bardziej dostępnym, co wyrzuciłoby wszystko z encapsualtion przez okno.

Taka zasada obowiązuje w twoim przypadku, nawet jeśli wystawiasz coś, co nie jest oryginalną wartością.

Nie można wykonać dokładnie tego, co próbowano. Musisz albo ustawić setera w klasie bazowej, albo użyć innej metody ustawiania nowej wartości.

+0

Klasa potomna nie może złamać enkapsulacji, ponieważ to, co robi, nie może zostać wykonane, chyba że hermetyzacja już została przerwana w klasie bazowej (jeśli dziecko nie powinno mieć dostępu do zaplecza nieruchomości). Również klasa podstawowa zadeklarowała własność jako wirtualną, co oznacza, że ​​powinna istnieć możliwość zmiany jej zachowania - a gdy właściwość/metoda jest wirtualna, wszystko idzie! (Tak długo, jak będziesz postępować zgodnie z jego dokumentacją.) To, czy powinno być wirtualne, czy też to, co łamie hermetyzację klasy bazowej, jest prawdziwym pytaniem, a to zależy. – AnorZaken

+0

@AnorZaken: O czym ty mówisz? To, że członek jest wirtualny, nie oznacza, że ​​możesz go zmienić w dowolny sposób. – Guffa

2

Można ukryć właściwość z klasy bazowej:

public new string Text 
{ 
    get { return differentText; } 
    set { differentText = value; } 
} 

Ale w takim razie, że nieruchomość będzie wykorzystywana tylko podczas manipulowania obiekt za pośrednictwem zmiennej tego typu, a nie typu baza

2

Chcesz, aby więcej możliwości zostało ujawnionych podczas korzystania z typu dziecka. Wygląda na to, że nie chcesz przesłonić, chcesz cienia. Wystarczy użyć nowego słowa kluczowego, aby ukryć własność Text tylko do odczytu w ramach własności do odczytu/zapisu.

W klasie bazowej:

protected string text; 
public string Text 
{ 
    get { return text; } 
} 

W klasie pochodnej:

new public string Text 
{ 
    get { return text; } 
    set { text = value; } 
} 
+0

Czy możesz jednocześnie cienia i przesłonić? – Svish

+0

Nie, mają na myśli różne rzeczy. To, czy cienie lub przesłonięcie określa, czy zachowanie Text ma wpływ nawet po rzutowaniu na typ bazowy. Sprawdź to pytanie, aby uzyskać lepsze wyjaśnienie: http://stackoverflow.com/questions/673779/what-is- shadowing –

Powiązane problemy