简体   繁体   中英

Instantiate a Type of a different type

Just from curiosity I've always seen code where a someone would instantiate an object of a curtain type then assign it to a different type. My question is why would you do that and what are we trying to accomplish eg:

SampleClassA sampleclassA = new SambleClassB();

What does this code mean is he trying to cast or what. Thanks in advance.

There are several cases where we would want to reference a subclass type with a supertype variable.

in your case doing:

SampleClassA sampleclassA = new SambleClassB(); 

will give you the flexibility of making the variable sampleclassA reference any type which derives from SampleClassA . that said you'd only want to do this when you have many types which derive from SampleClassA and you'd want to perform one of the actions mentioned below. if there is only one subtype of SampleClassA , then you'd rather just do SambleClassB sampleclassA = new SambleClassB(); .


Sometimes we can also use the supertype as a method parameter, method return type or the type of a collection of objects.

this:

  • enables us to create a method parameter which can take an input of any type which derives from the supertype, you can think of this as polymorphism in action.
  • equally, we can use the supertype as a method return type which will again enable us to return any type which derives from the supertype.
  • enables us to store a collection of objects which all derive from a particular type and perform some common logic upon all the objects within the collection.

Note that you can only do this if SampleClassB is "compatible" with SampleClassA . It could be that the former inherits from the latter, or the former implements the latter, or that the former can be implicitly converted to the latter.

In this answer I will only discuss the usefulness of the first two situations (inheritance and interface implementation) because I think the usefulness of the last situation (implicit conversion) is pretty clear.

Let's say you have 4 types like this:

interface IPet {
    ...
}

class Dog : IPet {
    ...
}

class Cat : IPet {
    ...
}

class Person {
    public IPet Pet { get; set; }
}

As you can see, every Person object can have a pet. This Pet property is declared as IPet . When you use this Person class, you will encounter the situation of assigning a Dog or Cat object to an IPet property:

Person me = new Person();
me.Pet = new Dog();

What is the purpose of declaring Pet as IPet then? "Why not declare it as Dog ? The above code will still work," you said. Well, if you did so, then a person object can't have those cute little cats as pets! What a pity! :)

Basically, declaring a property/variable as an interface, instead of a concrete class is usually because we want to store different types of objects in it in the future. This makes it more flexible, and it goes the same for base class/derived class.

I agree with the current answers, and wanted to add one more reason: because it reduces the entanglement between two separate bits of program.

Imagine I had a class like this:

public class Astronomy()
{
    public void CalculateOrbit()
    {
       Planet myVar = new Planet();
       // some code that does stuff with myVar
       // some *more* code that does stuff with myVar
       // etc
    }
}

That 'Astronomy' class - it's very entwined with your 'Planet' now. Any time you touch that Planet class, there's a good chance you're going to inadvertently break the larger Astronomy class.

But what about...

public class Astronomy()
{
    public void CalculateOrbit()
    {
       StellarObjectInterface myVar = new Planet();
       // some code that does stuff with myVar
       // some *more* code that does stuff with myVar
       // etc
    }
}

What's changed? You're still creating an instance of Planet... except now, you're putting it into a 'StellarObjectInterface' object. Now, whenever you operate on myVar, you're not able to just use any methods/properties/fields/etc from the Planet class willy-nilly - you have to go through the StellarObjectInterface.

What does this get you? It means as long as the Planet class obeys the interface it's implementing, you can change Planet around without having to worry about causing bad side-effects in the Astronomy class.

Better yet, you can do something like this:

public class Astronomy()
{
    public void CalculateOrbit(StellarObjectInterface myVar)
    {
       // some code that does stuff with myVar
       // some *more* code that does stuff with myVar
       // etc
    }
}

Now your Astronomy class isn't tied to Planet at all! Sure, you can pass in a Planet if you like, but you don't have to. You can pass in any Stellar Object.

Anyway, hope that makes sense. If you're interested in delving into this further, take a look at some of the SOLID principles for more info.

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