Accessing derived class properties when implementing an interface method with abstract base class as parameter
I tried hard to find an answer to this question, so if it is has been asked already, perhaps I'm wording it wrong. I have an abstract base class and a derived class.
abstract class Foo
{
protected int property1
protected int property2
// etc..
}
My dervied class contains some extra properties that are not found in the base class:
class Fum : Foo
{
public int UniqueProperty { get; set; }
}
Now I have an interface with a method that takes the abstract base class:
interface IDoSomethingWithFoos
{
void DoSomethingWithFoo(Foo fooey);
}
A class that implements the interface
class FumLover : IDoSomethingWithFoos
{
void DoSomethingWithFoo(Foo fooey)
{
// now in here i know i am going to be passed o开发者_C百科bjects 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;
}
}
So my question is: am I going about this in the right way? Although this compiles, I don't have enough code in place to make sure yet it is actually going to work properly. And my other question is: is this bad design? Is there a better way?
*
To elaborate a little more, because the natural response is, if you are going to be passing Fum, then have the interface method take a Fum instead of a Foo.
But let's say in my FumLover class, the method DoSomethingWithFoo deals 95% with properties that ARE in the abstract bass class. And let's say I have another derived class called Fie, which has a couple of unique properties. Now let's say I have a FieLover class, and I want to implement DoSomethingWithFoo because 95% of what I'm going to do here could apply to all Foo, but again, there is a little bit that is unique to Fie.
What is the alternative? To have an interface for each one: IDoSomethingWithFums, IDoSomethingWithFies, etc.? It seems like I lose all the abstraction for just that 5% of difference.
// now in here i know i am going to be passed objects of Fum
// and i want to access its unique properties
This is a clue that a design change might help. Your current interface says "I work on Foo
s". If the implementation only works on Fum
s, then you've got a mismatch in what you're saying and what you're doing. If you're really only expecting Fum
s, then declare the parameter in the interface as a Fum
.
If you don't want to do that, then using the as
syntax is preferable, since then you don't throw an exception when someone thinks they can pass in a Foo
(since hey, the interface says they can.)
The as
code should look like this:
Fum fumObj = fooey as Fum;
if (fumObj != null)
fumObj.UniqueProperty = 1;
Update:
Your suggestion of an interface for each derived class is actually preferable (since they say what they actually do,) but let's take a step back: what are you actually trying to accomplish here? If you want IDoSomethingWithFoos
to take advantage of Foo
's place as a base class (albeit an abstract one,) then you need to ensure that calling DoSomethingWithFoo
is meaningful for all Foo
s. If not, then you've already lost, since even though you claim to be a FooLover, you really only love Fum
s (or Fie
s.)
One solution would be do declare an abstract DoSomething()
method on Foo
itself. Now, you could have a List<Foo>
, and have code like this:
foreach (Foo foo in fooList)
foo.DoSomething();
Now you're actually taking advantage of abstraction. You don't care what kind of Foo
s those are: they all do something, possibly based on properties unique to only the derived class (no casting required.)
I think what you're doing is fine because Fum extends Foo you should be able to cast it in the way that you are.
Another approach would be to implement an IFoo interface and pass that into the method instead maybe.
精彩评论