简体   繁体   中英

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 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;

   }
}

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM