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.
InformationsquelleAutor Eric Anastas | 2009-07-23
Schreibe einen Kommentar