Hinzufügen einen set-accessor verfügt, um eine Eigenschaft in einer Klasse, abgeleitet von einer abstrakten Klasse mit nur ein get-accessor
Ich habe eine abstrakte Klasse, AbsClass, die eine Schnittstelle implementiert, IClass. IClass hat ein paar Eigenschaften, die nur mit Get-Accessoren. AbsClass implementiert die Eigenschaften von IClass als abstrakte Eigenschaften definiert werden, die in die Klassen, die sich von AbsClass.
Also all die Klassen, die sich von AbsClass müssen auch zu befriedigen IClass durch mit den gleichen Eigenschaften mit Get-Accessoren. In einigen Fällen jedoch möchte ich hinzufügen können, set-Accessoren der Eigenschaften von IClass. Doch wenn ich versuche zu überschreiben die abstrakten Eigenschaften in AbsClass mit einem set-accessor ich bekomme diese Fehlermeldung
ConcClassA.Unten.Set nicht überschreiben kann, weil AbsClass.Unten nicht haben eine überschreibbare set-accessor
Sehen ConcClassA unten.
Wenn ich eine Klasse, die nur die Umsetzung der IClass - Schnittstelle, nicht aber die Erben von AbsClass dann bin ich in der Lage, fügen Sie einen set-accessor mit Probleme. Sehen ConcClassB unten.
Konnte ich nur umsetzen, IClass bei jeder Ableitung von AbsClass dann eher direkt für AbsClass. Ich weiß aber von meinem design, dass jedes AbsClass muss auch ein IClass also würde ich eher angeben, dass die höher in der Hierarchie.
public interface IClass
{
double Top
{
get;
}
double Bottom
{
get;
}
}
abstract class AbsClass:IClass
{
public abstract double Top
{
get;
}
public abstract double Bottom
{
get;
}
}
class ConcClassA : AbsClass
{
public override double Top
{
get { return 1; }
}
public override double Bottom
{
get { return 1; }
//adding a Set accessor causes error:
//ConcClassA.Bottom.Set cannot override because AbsClass.Bottom does not have an overridable set accessor
//set { }
}
}
class ConcClassB : IClass
{
public double Top
{
get { return 1; }
//added a set accessor to an interface does not cause problem
set { }
}
public double Bottom
{
get { return 1; }
}
}
Update
So, ich denke das wird mehr Sinn machen, wenn ich genau erkläre, was ich versuche zu tun, eher dann mit dem abstrakten Beispiel. Ich arbeite in einem Architekturbüro und diese sind business-Objekte in Zusammenhang mit einem architektonischen design-Projekt.
Ich habe eine abstrakte Klasse RhNodeBuilding darstellt, eine Art des Gebäudes an einem Projekt. Es gibt einige Allgemeine Funktionen, wie die Fähigkeit zu haben, die Fußböden, das definiert ist in RhNodeBuilding. RhNodeBuilding erbt auch von anderen abstrakten Klassen, die es ermöglichen, Teil einer größeren Projekt-Baumstruktur.
RhNodeBuilding implementiert von einer Schnittstelle IBuilding definiert eine Reihe von nur-lese Eigenschaften, die alle Gebäude sollten in der Lage sein zu geben, wie TopElevation, BottomElevation, Höhe, NumberOfFloors, etc..etc.. Keep in Verstand, es gibt andere Gebäude-Typen, die nicht daraus RhNodeBuilding, aber noch implementieren müssen IBuilding.
Nun habe ich zwei Typen, die sich aus RhNodeBuilding: MassBuilding und FootPrintBuilding. MassBuilding ist definiert durch eine 3D-Form durch den Benutzer erstellt. Diese Form hat eine TopElevation und ein BottomElevation, dass zugegriffen werden soll, über die entsprechenden Eigenschaften, aber Sie sollten nicht in der Lage zu Bearbeiten Sie das 3D-Volumen durch änderung der Eigenschaften.
FootPrintBuilding auf der anderen Seite ist definiert durch eine geschlossene curve und einen Höhenbereich zu Extrudieren, dass die Kurve durch. So sollte nicht nur die Klasse zurückkehren können, was die aktuellen Erhebungen sind aber diese Erhebungen sollten auch in der Lage sein, um geändert werden, neu zu definieren, die Höhe reichen.
So in der Zusammenfassung. Alle Gebäude (IBuildings) müssen in der Lage sein, um wieder eine TopElevation und BottomElevation, aber nicht alle Gebäude ermöglichen sollte TopElevation oder BottomElevation zu direkt eingestellt werden. Alle RhNodeBuildings sind IBuildings, und Klassen, die sich von RhNodeBuilding möglicherweise oder möglicherweise nicht in der Lage sein müssen, direkt auf TopElevation und BottomElevation.
public interface IBuilding
{
double Top
{
get;
}
double Bottom
{
get;
}
}
abstract class RhNodeBuilding:IBuilding
{
public abstract double Top
{
get;
}
public abstract double Bottom
{
get;
}
}
class MassBuilding: AbsClass
{
//mass building only returns Top and Bottom properties so it works fine
public override double Bottom
{
get { return 1; }
}
public override double Top
{
get { return 1; }
}
}
class FootPrintBuilding: AbsClass
{
//Top and Bottom of FootPrintBuilding can both be retrieved and set
public override double Top
{
get { return 1; }
//adding a Set accessor causes error:
//cannot override because RhNodeBuilding.Top does not have an overridable set accessor
//set { }
}
public override double Bottom
{
get { return 1; }
//adding a Set accessor causes error:
//cannot override because RhNodeBuilding.Bottom does not have an overridable set accessor
//set { }
}
}
Recht jetzt scheint es die beste Möglichkeit ist, um nicht RhNodeBuilding implementieren IBuilding, sondern jede Klasse, die sich von RhNodeBuilding implementieren IBuilding. So kann ich die Definition der Eigenschaften von IBuilding direkt, eher dann wie übersteuert.
abstract class AltRhNodeBuilding
{
public abstract double Top
{
get;
}
}
class AltFootPrintBuilding: IClass
{
public override double Top
{
get { return 1; }
//Can't add set access to overridden abstract property
set { }
}
//No problem adding set accessor to interface property
public double Bottom
{
get { return 1; }
set { }
}
}
- Bist du nicht zu brechen die Schnittstelle "Vertrag" mit den Worten: "diese Eigenschaft ist manchmal nur-lese-manchmal aber auch nicht"? Vielleicht müssen Sie brechen auseinander Ihre Schnittstelle (andere Schnittstelle, zum Beispiel) zu ermöglichen, für diejenigen Klassen, die brauchen nur Lesen und andere, die müssen Lesen/schreiben.
- Fehlende property-accessor, bedeutet nicht, dass die Eigenschaft nur-Lesen für alle (D. H., dass es unveränderlich ist, und dessen Wert sich nie ändert) - es impliziert nur, dass die Eigenschaft nur-Lesen für client, verwendet diese bestimmte Schnittstelle. Also, Nein, es ist nicht das brechen Vertrag ändern. Es ist nur eine C#/CLR Einschränkung.
- Vereinbart, Schnittstelle Verträge nur angeben, was Sie umsetzen müssen, nicht das, was Sie nicht brauchen.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies funktioniert, wie es funktioniert, da die Eigenschaften nicht wirklich virtual - Ihre accessor-Methoden sind. So können Sie nicht überschreiben
set
wenn es nicht in der base-Klasse.Was Sie tun können, ist überschreiben und Schatten die Implementierung der Basisklasse, und stellen Sie Ihre eigene lese - /schreib-Eigenschaften. Ich kenne keine Möglichkeit, dies zu tun, ohne Einführung einer zusätzlichen Klasse in der Hierarchie:
Eine bessere Idee wäre, zu definieren, eine geschützte virtuelle Methode rechts in
AbsClass
und implementierenTop.get
undBottom.get
im Hinblick auf diese Methode. Dann können Sie überschreiben, die Methode direkt inConcClassB
, und shadow-die Eigenschaften, ohne die Notwendigkeit für eine extra-Klasse:Bin ich irgendwie neugierig, warum würden Sie wollen, dass diese Umsetzung den Klassen zu haben, die öffentliche setter-Methoden, die nicht Teil der öffentlichen Schnittstelle. Es klingt für mich wie Sie vielleicht eigentlich möchten, diese werden mehr eingeschränkt als öffentliche?
Andere als das, ich bin eine harte Zeit zu denken, ein problem mit diesem Ansatz. Wäre Sie "verstecken" alle Eigenschaften von der Superklasse, aber es gibt keine Eigenschaft setter in der Oberklasse sowieso, also das scheint ok. Es scheint, wie es möglicherweise die einfachste Lösung.
Verwenden Sie eine Globale variable.