C# 继承问题-声明同一属性的抽象和具体版本
好的,有两种选择,但在我开始之前,您需要知道:C# 继承问题-声明同一属性的抽象和具体版本,c#,oop,C#,Oop,好的,有两种选择,但在我开始之前,您需要知道: public abstract class GatewayBase { ... } public class Gateway : GatewayBase { ... } 备选方案#1 public abstract class ModelBase { public GatewayBase GatewayBase { get; private set; } // property named GatewayBase publi
public abstract class GatewayBase { ... }
public class Gateway : GatewayBase { ... }
备选方案#1
public abstract class ModelBase
{
public GatewayBase GatewayBase { get; private set; } // property named GatewayBase
public ModelBase(GatewayBase gateway)
{
GatewayBase = gateway;
}
}
public class Model : ModelBase
{
public Gateway Gateway { get; private set; } // property named Gateway
public Model(Gateway gateway)
: base(gateway)
{
Gateway = gateway;
}
}
备选方案2
public abstract class ModelBase
{
public GatewayBase Gateway { get; private set; } // property named Gateway
public ModelBase(GatewayBase gateway)
{
Gateway = gateway;
}
}
public class Model : ModelBase
{
public new Gateway Gateway { get; private set; } // property named Gateway plus "new" modifier
public Model(Gateway gateway)
: base(gateway)
{
Gateway = gateway;
}
}
讨论:
public abstract class GatewayBase { ... }
public class Gateway : GatewayBase { ... }
使用备选方案#1,具体类模型
可以“看到”网关的两个版本。一个称为GatewayBase
,另一个称为justGateway
,但它们都包含完全相同的实例。对于备选方案#2,从技术上讲,Gateway
仍有两个版本,但一个版本隐藏了另一个版本,因此实际上只有一个版本(除非使用base.Gateway
绕过它)。我喜欢这个替代方案#2让我无论身在何处都可以调用属性Gateway
,因为它在基本类和具体类中都被大量使用,而且它是一个简短但清晰的名称。尽管如此,我还是对以这种方式使用new
修饰符有些犹豫。这真的是一个隐藏财产的合法场景吗
您会选择哪一种,为什么选择?
或者可以自由地提出其他选择
谢谢
编辑:
public abstract class GatewayBase { ... }
public class Gateway : GatewayBase { ... }
我应该提到,
GatewayBase
和ModelBase
在一个依赖程序集中,因此它们对Gateway
和Model
一无所知。但是,Gateway
和Model
当然知道GatewayBase
和ModelBase
选项2看起来更干净,但不要创建单独的备份属性,而是通过将现有的基类属性从GatewayBase转换到Gateway来包装它。这样,您就不会对所使用的网关产生歧义:它总是相同的,只是从不同的角度:
public abstract class ModelBase
{
public ModelBase(GatewayBase gateway)
{
this.Gateway = gateway;
}
public GatewayBase Gateway { get; private set; }
}
public class Model : ModelBase
{
public Model(Gateway gateway)
: base(gateway)
{
}
public new Gateway { get { return (Gateway) base.Gateway; } }
}
您还可以使用泛型使不同类型的网关(有点像IEnumerable)更加灵活。泛型的问题是不能将一个C转换为另一个C(在4.0中有时可以)。解决这个问题的最干净的方法是引入一个非泛型接口,在泛型类上显式实现它。这样,当您与泛型实例交谈时,它就隐藏在视图之外,但您仍然可以混合使用C和C
公共接口IModel
{
GatewayBase网关{get;}
}
公共抽象类模型库:IModel
其中T:GatewayBase
{
公共模型库(TGateway网关)
{
this.Gateway=网关;
}
公用网关{get;专用集;}
GatewayBase IModel.Gateway{get{返回此.Gateway;}}
}
公共类模型:模型库
{
公共模型(网关)
:基本(网关)
{
}
}
我不确定您为什么想要第二个网关属性。网关是否具有与GatewayBase不同的接口?如果是这样的话,我看到了区别,但总的来说,我认为这可能不是最好的设计。我会认真考虑网关是否应该公开任何其他的属性/方法,而不是GatewayBase。如果不是,则不需要Model.Gateway属性
只有在两个类之间存在“is-a”关系时才使用继承是个好主意。这意味着Gateway“是”GatewayBase,通常应该具有相同的属性/方法,至少是公共属性/方法。谢谢,鲁本。我真的很喜欢创建一个属性而不创建单独的支持属性的想法。使用泛型也很有趣,但我认为这比我在这个特殊情况下需要的要多一些。
Gateway
是一个带有附加功能的GatewayBase
。这就像拥有一辆装有发动机、变速器和车轮的class汽车和一辆装有发动机、变速器、车轮和涡轮增压器的classFastCar:Car
。一辆快车就是一辆汽车——它能做汽车能做的一切,甚至更多。如果您有一个类FastCarDriver
,其属性类型为Car
(继承自Driver
),则每次您想对涡轮增压器进行操作时,都需要进行强制转换。因此,如果FastCarDriver
具有类型为FastCar
的属性,这将非常方便。