0

Let's consider this example:

public class Cat
{
    public virtual string Noise
    {
        get { return "Meow"; }
    }

    public Cat()
    {
    }
}

Cat provides some basic cat-related stuff, such as a Noise. By default, it is Meow.

public class AngryCat : Cat
{
    public AngryCat()
    {
    }

    public override string Noise
    {
        get { return "Angry Meow"; }
    }

    public void Bite()
    {
    }
}

AngryCat is a bit more angry and returns AngryMeow instead.

public static class CatFactory
{
    public static Cat GetCat()
    {
        return new AngryCat();
    }
}

CatFactory creates a new AngryCat, using the base class Cat as a type. So far so good.

Now, I want to pet that Cat.

static void Main(string[] args)
{
    Cat animal = CatFactory.GetAnimal();

    PetCat(animal);

    Console.ReadLine();
}

public static void PetCat(Cat animal)
{
    Console.WriteLine(animal.Noise);
}

The output is - as expected - Angry Meow. However, I've got a specific case where this is not what I want.

I`ve got an API that - for the sake of the example - only consumes Cat objects. It doesn't know about AngryCats. It's not a .NET application so it doesn't know the type, but rather that a Cat is related Meow.

Now, the people using the library don't know about this restriction because it's not something they should know. What I want to do is to actually downcast the AngryCat to Cat, so that the AngryCat specific property and methods are removed.

Casting, such as Cat animal = CatFactory.GetAnimal(); doesn't work because, well, it's still a AngryCat. I found out that I can use JSON.NET to serialize the AngryCat into a string and then deserialize that string into a Cat, which does what I want. But that seems rather hacky.

Is there something built-in that can help me out (except for writing a copy constructor)?

Shawn
  • 177
  • 7
  • I agree with the selection of the duplicate. Note that you have (at least) a few options here: 1) don't do that, just make the behavior specific to the derived class a member with a different name (my preferred...your design breaks polymorphism); 2) hide the base class member with `new` (not very good...member hiding makes the code much harder to understand); 3) add state the derived class can use to modify its behavior, and which is set before calling the virtual member (awkward, and harder to maintain, but at least it's clearer in the code what's going on) – Peter Duniho Jul 20 '20 at 16:35
  • See also https://stackoverflow.com/questions/1472701/what-is-the-use-case-for-c-sharp-allowing-to-use-new-on-a-virtual-method – Peter Duniho Jul 20 '20 at 16:35
  • It's important to understand the difference between the type of a variable and the type of the object to which it references. Casting an instance of `AngryCat` to `Cat` (`Cat aCat = CatFactory.GetCatByType("AngryCat")`) doesn't change the type of the object, it only changes how it is being referred to. – Flydog57 Jul 20 '20 at 22:41
  • For this particular problem, you might be able to get away with a `CatProxy` class (that inherits directly from `Cat` and it constructed with an instance of Cat or a Cat subclass). The proxy would normally pass function calls through to the Cat instance with which it was constructed, but, for certain methods, it would use it's own implementation (inherited from Cat). But consider if `Noise` used the Cat's age and weight, both private properties of a Cat, It would work in your (stateless) case, but not in a situation like that – Flydog57 Jul 20 '20 at 22:45

0 Answers0