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

我有一个抽象类, AbsClass实现了一个接口, IClassIClass有几个属性,只有Get访问者。 AbsClassIClass的属性实现为要在从AbsClass派生的类中定义的抽象属性。

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

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

请参阅下面的ConcClassA

如果我有一个只实现IClass接口但没有inheritance自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; } } } 

更新

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

我有一个抽象类RhNodeBuilding ,它代表项目中的一种类型的构建。 有一些通用function,例如在RhNodeBuilding中定义的具有楼层的functionRhNodeBuilding还inheritance自另一个抽象类,允许它成为更大的项目树结构的一部分。

RhNodeBuildingIBuilding接口实现,它定义了所有建筑应该能够提供的许多只读属性,如TopElevationBottomElevationHeightNumberOfFloors等等。请记住,还有其他建筑类型不能派生来自RhNodeBuilding ,但仍需要实施IBuilding

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

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

所以总结一下。 所有建筑物( 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 { } } } 

现在似乎最好的选择是不让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 { } } } 

这样做的方式是因为属性不是真正的虚拟 – 它们的存取方法是。 因此,如果基类中没有一个,则不能覆盖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 { ... } } } 

更好的想法是在AbsClass定义受保护的虚拟方法,并根据该方法实现Top.getBottom.get 。 然后,您可以直接在ConcClassB覆盖该方法,并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; } } 

我有点好奇为什么你希望这些实现类具有不属于公共接口的公共setter方法。 听起来像你可能真的希望这些比公众更受限制?

除此之外,我很难想到这种方法存在问题。 他们会“隐藏”超类中的任何属性,但是无论如何都没有超类中的属性设置器,所以这似乎没问题。 看起来这可能是最简单的解决方法。

使用全局变量。