我努力寻找这个问题的答案,所以如果已经有人问过,也许我说错了。我有一个抽象基类和派生类。
abstract class Foo
{
protected int property1
protected int property2
// etc..
}
我的dervied类包含一些在基类中找不到的额外属性:
class Fum : Foo
{
public int UniqueProperty { get; set; }
}
现在我有一个带有抽象基类的方法的接口:
interface IDoSomethingWithFoos
{
void DoSomethingWithFoo(Foo fooey);
}
实现接口的类
class FumLover : IDoSomethingWithFoos
{
void DoSomethingWithFoo(Foo fooey)
{
// now in here i know i am going to be passed objects of Fum
// and i want to access its unique properties
fooey.UniqueProperty = 1; // this doesn't work
((Fum)fooey).UniqueProperty = 1; // this seems to work
// as does..
Fum refToFum = fooey as Fum;
refToFum.UniqueProperty = 1;
}
}
所以我的问题是:我是否以正确的方式解决这个问题?虽然这个编译,我没有足够的代码来确保它实际上正常工作。我的另一个问题是:这是一个糟糕的设计吗?还有更好的方法吗?
*
详细说明一下,因为自然响应是,如果你要传递Fum,那么让接口方法采用Fum而不是Foo。
但是让我们说在我的FumLover类中,方法DoSomethingWithFoo使用抽象贝司类中的ARE属性处理95%。让我们说我有另一个名为Fie的派生类,它有几个独特的属性。现在假设我有一个FieLover类,我想实现DoSomethingWithFoo,因为我将要做的95%可以应用于所有Foo,但同样,有一点是Fie独有的。
有什么替代方案?为每个人提供一个接口:IDoSomethingWithFums,IDoSomethingWithFies等?似乎我失去了只有5%差异的所有抽象。
答案 0 :(得分:4)
// now in here i know i am going to be passed objects of Fum
// and i want to access its unique properties
这是设计变更可能有所帮助的线索。您当前的界面显示“我正在使用Foo
s”。如果实现只适用于Fum
s,那么你所说的和你正在做的事情就不匹配了。如果您真的只期望Fum
s,那么将接口中的参数声明为Fum
。
如果您不想这样做,那么最好使用as
语法,因为当有人认为可以传入Foo
时,您不会抛出异常(因为嘿) ,接口表示他们可以。)
as
代码应如下所示:
Fum fumObj = fooey as Fum;
if (fumObj != null)
fumObj.UniqueProperty = 1;
<强>更新强>:
你对每个派生类的接口的建议实际上是可取的(因为他们说明了他们实际做了什么),但让我们退后一步:你实际上想要在这里完成什么?如果您希望IDoSomethingWithFoos
利用Foo
的位置作为基类(尽管是抽象的基类),那么您需要确保调用DoSomethingWithFoo
对所有{{1}都有意义}}秒。如果没有,那么你已经输了,因为即使你声称是一个FooLover,你真的只爱Foo
s(或Fum
s。)
一种解决方案是在Fie
本身上声明abstract DoSomething()
方法。现在,您可以拥有Foo
,并且代码如下:
List<Foo>
现在你实际上正在利用抽象。你不关心它们是什么类型的foreach (Foo foo in fooList)
foo.DoSomething();
:它们都做了一些事情,可能是基于仅对派生类唯一的属性(不需要强制转换。)
答案 1 :(得分:-1)
我认为你所做的很好,因为Fum扩展了Foo你应该能够以你自己的方式投射它。
另一种方法是实现IFoo接口并将其传递给方法。