Link to home
Start Free TrialLog in
Avatar of ianinspain
ianinspain

asked on

500pts: Help on instantiating an object

Hi there,

I was reading over one of my c# books about instancing an object, which of course i already do... But i come across something puzzled me and wanted to know why.

Basically its an example in the book that states there are 2 classes. GenericCustomer and Nevermore60Customer (which inherits from base class Generic Customer).

It states to create an instance do the following :

GenericCustomer customer = new Nevermore60Customer();

That confused me, actually maybe i am going crazy but why can't you just do

Nevermore60Customer customer = new Nevermore60Customer();

why must you use GenericCustomer in front?? if you see my mean....

Can anybody clear this up for me?

Thanks in advance

Ian
Avatar of mrichmon
mrichmon

You can just do
Nevermore60Customer customer = new Nevermore60Customer();

and in fact in that case customer is more specific.

But let's say you had two classes

Nevermore60Customer and Nevermore100Customer.

Then let's say you had a function that you wanted to do the same thing on both of these types of customer. You could do this:

int DoSomething(GenericCustomer customer)
{ ...
}

and you could then do either:

int myreturn = DoSomething(new Nevermore60Customer ());

or

int myreturn = DoSomething(new Nevermore100Customer ());

Both would work.

So basically in this line:
GenericCustomer customer = new Nevermore60Customer();

You are just using "customer" like it is a GenericCustomer, even though it is a more specific type of Nevermore60Customer.

In general if you know the type you should use the more specific type, and only use the parent type as in that example line of code in the book, if the variable may need to contain different child types.
SOLUTION
Avatar of mrichmon
mrichmon

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Fernando Soto
Hi ianinspain;

The book most likely was talking about polymorphism. This is the ability of an object to look like another object. In this case the author declared the variable customer as follows:

GenericCustomer customer = new Nevermore60Customer();

So he created a variable customer of type GenericCustomer and assigned an object of type Nevermore60Customer which is fine because he is derived from GenericCustomer. You also could have done it the way you stated and the statement would have compiled. Here is the difference. Let say I have a class called GenericCustomer that looks like this:

      public class GenericCustomer
      {
      
            public int gCustomer = 10;
            
            public GenericCustomer()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }
      }

And a class derived from it as follows:

      public class Nevermore60Customer : GenericCustomer
      {
      
            public int nCustomer = 70;
      
            public Nevermore60Customer()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }
      }

And you execute the following command:

GenericCustomer customer = new Nevermore60Customer();

You will be able to access the variable gCustomer from that object like this customer.gCustomer but you could not access nCustomer from that object because the variable customer is of type GenericCustomer. But if we were to do this:
Nevermore60Customer customer2 = (Nevermore60Customer ) customer

Now you have access to both gCustomer and nCustomer from the variable customer2.

An example of how this is used could be seen when we declare an ArrayList and add an object to it, which has the definition:

public virtual int Add( object value );

Not that the parameter passed to the array list is of type object, which is the object that all objects are derived from. Sot to add it to the list we do something like this:

ArrayListName.Add(customer2);

Now this is fine because customer3 is derived from type object somewhere up the line. Now when we want to get that customer2 back we can do something like:

Nevermore60Customer  mycustomer = (Nevermore60Customer  ) ArrayListName.Item(1);

Because the Item property returns an object we had to cast the return object.

I hope that this was of some help.

Fernando
Hi ianinspain;

Type O, this is the way it should have read above.

Note that the parameter passed to the array list is of type object, which is the object that all objects are derived from. So to add it to the list we do something like this:

Ans this one as well:

Now this is fine because customer2 is derived from type object somewhere up the line. Now when we want to get that customer2 back we can do something like:

Fernando
Avatar of ianinspain

ASKER

wow thanks both, its beggining to sink in now...

What i can't really understand is: Why would i want Nevermore60Customer is look like GenericCustomer?

Technically Nevermore60customer is inherited from GenericCustom anyway so whats the point?

Also if I use

GenericCustomer customer = new Nevermore60Customer();

then technically I am assigning Nevermore60Customer to GenericCustomer which is fine as it derives from it BUT if i use the method then any static fields that belong only to Nevermore60Customer are not available to me as it is a GenericCustomer - so why even bother ... why not just do

GenericCustomer customer = new GenericCustomer();

So if i am assigning Nevermore60Customer to a genericcustomer i.e. GenericCustomer customer = new Nevermore60Customer();

does this mean that any methods that were declared in Nevermore60Customer as now not available to me because I am using GenericCustomer?

I think i am almost there, i just can't understand what the realworld example would be? If assigning Nevermore60Customer to GenericCustomer (polymorphism) then i lose all the extra functionality of Nevermore60Customer so i could have just used generic customer in the beggining..

Thanks once again for your continued help on this

Ian
I must admit i would always do this

Nevermore60Customer customer = new Nevermore60Customer();

because if i needed to override anything then i could using virtual...

but why making it look like its base class is strange...

Almost there i think :-)

Ian
Again, you would do that only if you needed the variable to act as a "pointer" to an unknown child instance type.

So for example using something I actually do.  We have a project that runs rules.  Each rule is a class that MUST inherit from a class called BaseRule.

So we have:

class BaseRule {...}

then

class Rule1: BaseRule { ... }
class Rule2: BaseRule { ... }

etc...

The BaseRule (which is abstract by the way) forces child types to define a function called RunRule which takes in a person object

So we can do this:

BaseRule rule;
Person bob = new Person("Bob");

rule = new Rule1();

rule.RunRule(bob);

rule = new Rule2();

rule.RunRule(bob);

Notice that "rule" is of type BaseRule.

Now in actuality we dynamically load the rules from different assemblies based on an xml file so we don't know what the rule name is in advance, but since we do know that it is of type BaseRule then we know we can declare a variable of that type and assign any child rule to that variable, and call the RunRule based on that parent "rule" instance, which actually points to a more specific child instance.


Does that make sense?
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Also, lets take my last example one step further. Lets say we want to create an animal and have it speak, but lets say that we create the animal based on a string which represents which animal we want to create. Okay, this one is a little more complex, but you'll get it.

We have a textbox. The user types in which animal they want to hear speak, then they click the button and then we create an animal based on what the user put in the textbox and make it speak. This is a quick example of how we can create an animal at run-time and still call the speak method. Notice that we need to create an instance of Animal in order for this to work properly, we can't make it a concrete Dog object because we don't know that the user wants a dog, we just know that they want an animal.

This example uses a textbox and a button.

Notice that we create an animal based on what the user typed in the textbox. We can then run that animal through the same MakeAnimalSpeak method, and everything works peachy.

private void button1_Click(object sender, EventArgs e)
{
    string animalType = textBox1.Text.Trim();
    Animal animal = CreateAnimal(animalType);
    MakeAnmialSpeak(animal);
}


Okay here is a method where we create an animal based on a string that is passed through. If they pass through "dog" then we create a dog, if they pass through "cat" then we create a cat. If they pass anything else then we will just return null because there are no other animals (yes, this method could be more robust, but I am trying to make it easier to understand)

private Animal CreateAnimal(string animalType)
{
    if (animalType.ToLower() == "dog")
    {  
        return new Dog();  //dog was passed through, return a dog
    }
    else if (animalType.ToLower() == "cat")
    {
         return new Cat(); //cat was passed through, return a cat
    }
    else
    {
         return null;  //well, it wasnt a dog or a cat, so return null
    }
}



Okay here is the "new" MakeAnimalSpeak method. If the animal isnt' null, then we will make it speak. Notice that this method doesn't care which animal it is, as long as it isn't null we can make it speak

private void MakeAnmialSpeak(Animal animal)
{
    if (animal != null)
    {
        animal.Speak();
    }
    else
    {
        MessageBox.Show("Unknown Animal");
    }
}


Okay, here is where all the action happens. We get the string that the user inputs. Then we run that string through a method called CreateAnimal. Now after that we have an animal and we can make it speak regardless of which animal it is. We can't do this if we used a more concrete type, ie, it wouldn't work if we said Dog myDog = CreateAnimal(animalType) because we don't know that it's going to be a dog.

private void button1_Click(object sender, EventArgs e)
{
    string animalType = textBox1.Text.Trim();
    Animal animal = CreateAnimal(animalType);
    MakeAnmialSpeak(animal);
}

This example may seem a bit tricky, but if you really look at it, then I know that you will understand the benefit of of it. I use polymorphism all the time! it can be extremely useful!
oops, it's not supposed to be "MakeAnmialSpeak" (Animal, not Anmial!--- doh!), but lucky (because of intellisense) the mispelling is consistant, so you can probably copy-paste the code and it will still work
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks everyone for all your comments, after your explanations and digging a little deeper into polymorphism... I got it now....

Its probably something i won't use that much but it is nice to understand it fully..

a big thanks again to everyone involved

Ian
you'd be suprised how much you use polymorphism, actually.

Once you fully understand how to construct your objects and have a really good grasp on OOP, it becomes second nature to build classes that take full advantage of OOP constructs, including polymorphism.