在以下场景中,我对以何种方式继续提出建议表示感谢。让我们看看我是否可以清楚地解释它(英语不是我的母语,所以事情可能会让人感到困惑,对不起)。
假设我有以下接口:
internal interface IBlah
{
int Frob();
}
internal interface IBlahOnSteroids: IBlah
{
double Duh();
}
现在我们有一个与IBlah对象有'has'关系的Foo类:
public class Foo
{
IBlah blah;
internal Foo(IBlah blah)
{
this.blah = blah;
}
public int Frob()
{
....
return this.blah.Frob();
}
}
现在我们还需要一个与IBlahOnSteroids对象具有'has'关系的FooOnSteroids类。 问题是,知道IBlahOnSteroids的一部分已经在Foo中实现了,如果我们创建了会发生什么 FooOnSteroids继承自Foo?
我们会得到这样的结果:
public class FooOnSteroids: Foo
{
IBlahOnSteroids blah;
internal FooOnSteroids(IBlahOnSteroids blah)
:base(blah)
{
this.blah = blah;
}
public double Duh()
{
return this.blah.Duh();
}
}
这是推荐的模式吗?我们将继承链传递给相同的'blah'对象,并且在每个“级别”我们将它存储在私有中 具有“有用”类型的字段。我可以看到,我无法在BlahBase中存储受保护的属性 暴露了一个常见的IBlah参考所有下降类,因为它必须是IBlah类型,对BlahOnSteroids没用。这种情况是否均匀 推荐的?或者我们应该只将Foo和FooOnSteroids实现为没有继承的独立类(这会产生代码重复)?也许它绝对可以做到这一点,但它不知何故感觉像一个黑客。是吗?
使用泛型的选项,可以立即解决问题,这是不可能的,因为我知道这很糟糕,这个库必须以.Net 1.x平台为目标。
只是实现BlahOnSteroids的选项也是可能的,但这意味着取决于调用者,我们将不得不抛出异常,如果有的话 IBlahOnSteroids成员被召唤。我不喜欢那样。
非常感谢任何建议!
答案 0 :(得分:2)
一种替代模式是
public class Foo
{
protected IBlah Blah { get; private set; }
...
}
public class FooOnSteroids : Foo
{
private new IBlahOnSteroids Blah { get { return (IBlahOnSteroids)base.Blah; } }
...
}
但是,这与您的代码没有太大区别;如果你不能使用泛型,它们都很好。
答案 1 :(得分:2)
您可以通过使基本字段可用来减少重复:
IBlah blah;
protected IBlah Blah { get { return blah; } }
并在子类型中进行投射(因为您希望您选择blah
得到尊重):
public double Duh() {
return ((IBlahOnSteroids)Blah).Duh();
}
你也可以在基类型上做泛型(避免演员),但我不确定它是否值得。但请注意,如果基类决定注入装饰器blah
(如果装饰器不提供第二个接口),则可能会爆炸。
答案 2 :(得分:1)
在回答你关于删除Foo和FooOnSteroids之间继承的问题时,我不知道你的所有推理,但我可以尝试提供一些一般性的指导。您应该考虑使用继承主要是为了让您的客户能够使用FooOnSteroids实例,但只编写Foo的代码。
因此,如果从概念上讲,您的客户会这样做:
Foo foo = new FooOnSteroids();
foo.Frob()
你应该保留继承权。
如果您只是为了重用代码而创建继承关系,我建议您考虑重构类以包含提供共享功能的类。继承不是代码重用的最佳模式。
答案 3 :(得分:1)
鉴于您不能使用泛型(可能会或可能不会使您的特定用例更容易),我个人会选择投射blah
成员Foo
。使用C#进行投射相对无痛:
public double Duh()
{
return (this.blah as IBlahOnSteroids).Duh();
}
如果无法将对象强制转换为您请求的类型,则C#中的as
关键字将评估为null
。在上面的示例中,如果this.blah
不是IBlahOnSteroids
的实例,您将获得NullReferenceException
。您可以检查对象是否是类似的实例:
public double Duh()
{
if (this.blah is IBlahOnSteroids)
return (this.blah as IBlahOnSteroids).Duh();
else
throw new InvalidTypeException("Blah is not an instance of IBlahOnSteroids");
}
虽然在原始示例的代码中,blah
的{em>可能不应该是IBlahOnSteroids
的实例,因为它是在构造函数中分配的,这使得在编译时为你断言。