2012-02-20 10 views
5

Dlaczego jest to, że po to legalne C#:Dodawanie akcesor interfejs nieruchomość dozwolone, ale nie do abstrakcyjnej własności

public interface ISomeInterface 
{ 
    int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassImplementingInterface : ISomeInterface 
{ 
    public int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

ale to nie jest:

public abstract class SomeAbstractClass 
{ 
    public abstract int SomeProperty 
    { 
     get; 
    } 
} 

public class SomeClassExtendingAbstractClass : SomeAbstractClass 
{ 
    public override int SomeProperty 
    { 
     get { return 32; } 
     protected set {} 
    } 
} 

Te ostatnie wyniki w następujących błąd kompilacji:

'InterfaceAbstractTest.SomeClassExtendingAbstractClass.SomeProperty.set': cannot override because 'InterfaceAbstractTest.SomeAbstractClass.SomeProperty' does not have an overridable set accessor InterfaceAbstractTest

Jaki jest powód, dla którego nie wolno zabronić drugiej z nich przy jednoczesnym umożliwieniu tego pierwszego?

+0

Myślę, że tutaj słowo "kay" to "przesłonięcie". Nie ma ustalonej metody do przesłonięcia. –

+0

A może to, że słowo kluczowe "override" jest określone na poziomie właściwości, a nie na poziomie akcesora? W końcu każdy akcesor jest odrębną metodą, jeśli chodzi o to. –

+1

W prawo - słowo kluczowe abstrakcyjne działa na poziomie właściwości, a nie na poziomie akcesora. –

Odpowiedz

3

Ponieważ dzwoniący pomocą interfejsu troszczy się tylko, że realizator interfejsu przynajmniej realizuje definicję interfejsu użytkownika, jak @davisoa stanach, natomiast SomeAbstractClass W przykładzie definiuje zamówienia publicznego, które stwierdza dokładnie typ, dostępność i (dla właściwości) czytelność/writability członków.

Jeśli używasz odbicia, aby uzyskać PropertyInfo z SomeProperty (z bazy lub klasy podrzędnej), to musi to gdzieś rozwiązać. Dopuszczenie, aby klasa podrzędna zmieniała czytelność/zdolność do pisania, byłaby tyleż naruszeniem umowy, co zmianą typu zwrotu lub listy argumentów.

Wyobraźmy sobie na przykład:

SomeAbstractClass sc = new SomeClassExtendingAbstractClass(); 
PropertyInfo pi = sc.GetType().GetProperty("SomeProperty"); 
Console.Out.WriteLine(pi.CanWrite); // What should be printed here? 
2

Dzieje się tak, ponieważ implementacja interfejsu składa obietnicę, że będzie dostępna właściwość SomeProperty, którą można "pobrać".

Abstrakcyjna implementacja klasy składa obietnicę, że zajęcia dla dzieci będą zapewniać implementację właściwości SomeProperty za pomocą publicznej metody pobierania.

W końcu klasa bazowa jest określenie czegoś, co musi być nadpisane, natomiast interfejs jest zdefiniowanie kontrakt.

+0

O ile mi wiadomo, 'SomeClassExtendingAbstractClass' * nie * udostępnia właściwość' SomeProperty' z publiczną metodą pobierania. Dla każdego, kto działa przeciwko abstrakcyjnemu interfejsowi, nie ma znaczenia, że ​​istnieje także seter. Stąd moje pytanie. Wyobraź sobie, że zamiast tego każdy z get/set byłby metodami. Wyobraź sobie, że nie możesz podać metody "SetValue" tylko dlatego, że rozszerzyłeś klasę abstrakcyjną o metodę "GetValue". –

+2

@KentBoogaart to wszystko - nie są to tylko kolekcjonerowie. Właściwości są pierwszorzędnymi obywatelami w .NET i mają metadane kontraktu dotyczące ich czytelności/zapisywalności związanej z własnością. –

1

Próbujesz przesłonić ustawiony operator, który nie istnieje. Zdefiniuj ustaloną część właściwości w klasie abstrakcyjnej lub nie próbuj definiować jej w konkretnej klasie. Ponieważ masz zestaw chroniony w klasie konkretnej, domyślam się, że chcesz ustawić chroniony operator zestawu w definicji abstrakcyjnej.

0

Konieczne jest, aby zarówno zastąpić istniejący obiekt i cień go nowym odczytu jeden. Niestety, .net nie zapewnia żadnych środków do nadpisania i zacienienia członka w ramach jednej klasy. Najlepszą rzeczą, jaką można zrobić, jest prawdopodobnie zdefiniowanie przez abstrakcyjną klasę bazową konkretnej nie-wirtualnej właściwości tylko do odczytu, której getter wywołuje funkcję abstrakcyjną. Klasa pochodna może następnie śledzić właściwość za pomocą nie-wirtualnej funkcji odczytu i zapisu, która wywołuje tę samą funkcję w swoim programie pobierającym i nową funkcję abstrakcyjną lub wirtualną w jej ustawieniu.

1

Jest to zgodne z projektem. Cytuję ze specyfikacją C# językowych:

An overriding property declaration must specify the exact same accessibility modifiers, types and name as the inherited property, if the inherited property has only a single accessor (i.e.,... ready only or write-only), the overriding property must include only that accessor.

Powodem tego decesion może być dlatego, że interfejsy są bardziej elastyczny rodzaj umów niż klas abstrakcyjnych. Interfejsy dotyczą tylko najmniej wspólnego mianownika, a nie całego wdrożenia. Sądzę, że istnieją dobre powody, aby wybrać jeden wzór nad drugim.

Powiązane problemy