C# Extending Classes and Overriding Types

I have a scenario where I am working with a 3rd party library that I cannot change, and I'm trying to figure out a way to work with some of their types. Basically, they have the following classes:
public class Food
{
    ... properties that apply to all food ...
}
public class Pie : Food
public class Grapefruit : Food
{
   public int NumberOfSeeds = 50;
}
public class Cherry : Food
{
   public int NumberOfSeeds = 1;
}

Open in new window

Now, "Grapefruit" and "Cherry" both have the "NumberOfSeeds" property, but that property is not part of the Food class.

I'm working on a "helper" class that removes seeds, so I'm trying to do something like this:
public class FoodHelper
{
  public Food item;

  public void RemoveSeeds()
  {
    item.NumberOfSeeds = 0;
  }
}

public class GrapefruitHelper : FoodHelper
{
  new public Grapefruit item;
}

public class CherryHelper : FoodHelper
{
  new public Cherry item;
}

Open in new window

I'm trying to avoid having to redefine "RemoveSeeds" over and over again in the child classes (the real method is pretty monstrous), but when I define it in the parent class, I get a warning that "Food" doesn't contain the "NumberOfSeeds" property, which is correct.

Also, if I try to use any valid type like "Cherry" instead of "Food" in the parent class in order to make the RemoveSeeds work, then I'm forced to override / hide the "item" in the child classes and the parent methods don't even see the right "item".

I've experimented with trying to use dynamic <T> types in my class definitions, but with no luck. Can anyone point me in the right direction here?
LVL 38
gr8gonzoConsultantAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

käµfm³d 👽Commented:
As you may know, you cannot modify a class that is provided to you by another party. If it is not your code, then you cannot modify it. If a class is not sealed, then you can extend it, but you cannot alter the original class' definitions. If the original class provides any virtual properties or methods, then you can override that behavior within a child class, but that still doesn't grant you access to changing the original class' logic.

With that said, ordinarily I'd say you need some abstraction, but since Food doesn't provide the NumberOfSeeds property to either class, there is no commonality (so far as the runtime is concerned) between the two classes. I think your only recourse is going to be to use Reflection, which will incur a bit of a performance hit (which may or may not make a difference in your app).
0
gr8gonzoConsultantAuthor Commented:
To be clear, all the code is owned by my company, but the problem is in a portion of the code developed by another department, and it cannot be resolved without going through another cycle that takes too long for my current project task. I actually do have access to the source code, but cannot just compile my own version of that class without bringing along a thousand dependencies. I am only writing a plugin for this product, so that's the predicament.

I was hoping to avoid Reflection for the performance hits you mentioned. Is there a way to define a -new- type "group" like "Fruit" that tells .NET that "This parameter called Fruit will always be either Cherry or Grapefruit?"
0
käµfm³d 👽Commented:
No. You can create a new group, but you will have no way of telling that group that both Cherry and Grapefruit have the NumberOfSeeds field.

From what you have stated, I suppose that even this is not going to be plausible for your timelines, but what could also happen--with minimal impact--is that you have the owning group create a new interface definition that desribes this common data:

public interface ISeededFood
{
    int NumberOfSeeds { get; set; }
}

Open in new window


...and then the other classes just implement that interface:

public class Grapefruit : Food, ISeededFood
{
    public int NumberOfSeeds = 50;

    public int NumberOfSeeds
    {
        get { return this.NumberOfSeeds; }
        set { this.NumberOfSeeds = value; }
    }
}
public class Cherry : Food, ISeededFood
{
   public int NumberOfSeeds = 1;

    public int NumberOfSeeds
    {
        get { return this.NumberOfSeeds; }
        set { this.NumberOfSeeds = value; }
    }
}

Open in new window


None of the existing code needs to change, and now you have something common between the two classes. You can now create a method that takes in the interface, which will allow you to pass an instance of either class to that method.

public void RemoveSeed(ISeededFood food)
{
    food.NumberOfSeeds--;
}

Open in new window


Note:  I didn't change your field name, but in .NET the convention is to name fields (a.k.a. class-level variables) with camel case (e.g.  numberOfSeeds). The demonstration above might actually yield an infinite loop since I named the property the same name (case relevant) as the field. Camel-casing of the field name would alleviate this.
0
gr8gonzoConsultantAuthor Commented:
No, this approach can't work because I don't have that level of access over the Grapefruit and Cherry classes, so I can't define them any further.

I ended up rewriting things into nested classes. Not ideal, but it works...
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gr8gonzoConsultantAuthor Commented:
Gave all the points to kaufmed for the help, but the ultimate answer here was a different approach to the code.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
.NET Programming

From novice to tech pro — start learning today.