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的类型:MassBuilding和FootPrintBuilding.MassBuilding由用户创建的3D形状定义.该形状具有可通过相应属性访问的TopElevation和BottomElevation,但您不能通过更改属性来编辑3D卷.
另一方面,FootPrintBuilding由闭合曲线和高度范围定义,以挤出该曲线.因此,班级不仅应该能够返回当前的高程,而且还应该能够改变这些高度以重新定义高度范围.
所以总结一下.所有建筑物(IBuildings)都需要能够返回TopElevation和BottomElevation,但并非所有建筑物都应允许直接设置TopElevation或BottomElevation.所有RhNodeBuilding都是IBuildings,从RhNodeBuilding派生的类可能需要也可能不需要能够直接设置TopElevation和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 { }
}
}
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.get与Bottom.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)