好的,有两种选择,但在我开始之前,你需要知道这一点:
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;
}
}
讨论:
使用备选方案#1,具体类Model
可以“看到”两个版本的Gateway
。一个称为GatewayBase
,另一个称为Gateway
,但它们都包含完全相同的实例。对于备选方案#2,从技术上讲,仍有两个版本Gateway
,但有一个隐藏另一个版本,因此实际上只有一个版本(除非您使用base.Gateway
绕过它)。我喜欢替代#2让我可以在任何地方调用属性Gateway
,因为它在基础类和具体类中都得到了很多使用,而且它是一个简短但清晰的名称。不过,我对以这种方式使用new
修饰符犹豫不决。这真的是隐藏房产的合法方案吗?
您会选择哪个以及为什么?
或者随意提出其他选择。
感谢。
修改
我应该提到GatewayBase
和ModelBase
位于依赖程序集中,因此他们对Gateway
和Model
一无所知。但是,Gateway
和Model
当然知道GatewayBase
和ModelBase
。
答案 0 :(得分:2)
选项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< T>)。泛型的问题在于你不能施放一个C< X>。另一个C< Y> (好吧,有时你可以在4.0)。解决这个问题的最简单方法是引入一个非泛型接口,您可以在泛型类上显式实现。这样,当您与通用实例交谈时,它就会隐藏起来,但您仍然可以混合使用C< X>和C< Y&gt ;.
public interface IModel
{
GatewayBase Gateway { get; }
}
public abstract class ModelBase<TGateway> : IModel
where T : GatewayBase
{
public ModelBase(TGateway gateway)
{
this.Gateway = gateway;
}
public TGateway Gateway { get; private set; }
GatewayBase IModel.Gateway { get { return this.Gateway; } }
}
public class Model : ModelBase<Gateway>
{
public Model(Gateway gateway)
: base(gateway)
{
}
}
答案 1 :(得分:0)
我不确定你为什么要第二个Gateway属性。 Gateway是否具有与GatewayBase不同的接口?如果是这样,我看到了差异,但一般来说我认为它可能不是最好的设计。我会认真考虑Gateway是否应该公开除GatewayBase之外的任何其他属性/方法。如果没有,那么您不需要Model.Gateway属性。
当两个类之间存在“Is A”关系时,最好只使用继承。这意味着Gateway“Is A”GatewayBase并且通常应该具有相同的属性/方法,至少是公共的。