将set访问器添加到类中的属性,该类派生自仅具有get访问器的抽象类

Eri*_*tas 16 c# abstract-class properties interface

我有一个抽象类,AbsClass实现了一个接口,IClass.IClass有几个属性,只有Get访问器.AbsClass实现的属性ICLASS为抽象属性,以在从派生的类中定义AbsClass.

因此,从AbsClass派生的所有类也需要通过与Get访问器具有相同的属性来满足IClass.但是,在某些情况下,我希望能够从IClass向属性添加set访问.然而,如果我尝试使用set访问器覆盖AbsClass中的抽象属性,我会收到此错误

ConcClassA.Bottom.Set无法覆盖,因为AbsClass.Bottom没有可覆盖的set访问器

请参阅下面的ConcClassA.

如果我有一个只实现IClass接口但没有继承自AbsClass的类,那么我可以添加一个没有问题的set访问器.请参阅 下面的ConcClassB.

我可以在AbsClass的每个派生中实现IClass,而不是直接为AbsClass实现.但是我从我的设计中知道每个AbsClass也需要一个IClass,所以我宁愿在层次结构中指定更高的值.

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; }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新

因此,如果我准确地解释我正在尝试做什么而不是使用抽象示例,我认为这将更有意义.我在一家建筑公司工作,这些是与建筑设计项目相关的业务对象.

我有一个抽象类RhNodeBuilding,它表示项目中的一种类型的构建.有一些通用功能,例如在RhNodeBuilding中定义的具有楼层的功能.RhNodeBuilding还继承自另一个抽象类,允许它成为更大的项目树结构的一部分.

RhNodeBuilding从接口实现IBuilding定义只读属性,所有的建筑物应能提供如一些TopElevation,BottomElevation,身高,NumberOfFloors,etc..etc ..请记住有没有获得其他建筑类型来自RhNodeBuilding,但仍需要实施IBuilding.

现在我有两种派生自RhNodeBuilding的类型:MassBuildingFootPrintBuilding.MassBuilding由用户创建的3D形状定义.该形状具有可通过相应属性访问的TopElevationBottomElevation,但您不能通过更改属性来编辑3D卷.

另一方面,FootPrintBuilding由闭合曲线和高度范围定义,以挤出该曲线.因此,班级不仅应该能够返回当前的高程,而且还应该能够改变这些高度以重新定义高度范围.

所以总结一下.所有建筑物(IBuildings)都需要能够返回TopElevationBottomElevation,但并非所有建筑物都应允许直接设置TopElevationBottomElevation.所有RhNodeBuilding都是IBuildings,从RhNodeBuilding派生的类可能需要也可能不需要能够直接设置TopElevationBottomElevation.

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 { }
    }

}
Run Code Online (Sandbox Code Playgroud)

现在似乎最好的选择是不要让RhNodeBuilding实现IBuilding,而是让每个派生自RhNodeBuilding的类实现IBuilding.这样我就可以直接从IBuilding定义属性,而不是覆盖.

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 {  }
    }
}
Run Code Online (Sandbox Code Playgroud)

Pav*_*aev 10

这样做的方式就是因为属性不是真正的虚拟 - 它们的存取方法是.因此,set如果基类中没有一个,则无法覆盖.

您可以做的是覆盖和隐藏基类实现,并提供您自己的新读/写属性.如果不在层次结构中引入额外的类,我不知道有任何方法可以做到这一点:

class AbsClassB : AbsClass
{
    public override double Top { get { return ((ConcClassB)this).Top } }
    public override double Bottom { get { return ((ConcClassB)this).Bottom } }
}


class ConcClassB :  AbsClassB
{
    new public double Top
    {
        get { ... }
        set { ... }
    }

    new public double Bottom
    {
        get { ... }
        set { ... }
    }
}
Run Code Online (Sandbox Code Playgroud)

一个更好的想法是正确的定义一个受保护的虚拟方法AbsClass,并实现Top.getBottom.get该法的条款.然后,您可以直接覆盖该方法ConcClassB,并隐藏属性,而无需额外的类:

abstract class AbsClass : IClass
{
    public double Top
    {
        get { return GetTop(); }
    }

    public double Bottom
    {
        get { return GetBottom(); }
    }

    protected abstract double GetTop();

    protected abstract double GetBottom();
}

class ConcClassB :  AbsClass
{
    new public double Top
    {
        get { ... }
        set { ... }
    }

    new public double Bottom
    {
        get { ... }
        set { ... }
    }

    protected override double GetTop()
    {
        return Top;
    }

    protected override double GetBottom()
    {
        return Bottom;
    }
}
Run Code Online (Sandbox Code Playgroud)