views:

136

answers:

6

I have a question related to OOPS concept.

I have a base class

public class BaseClass
{
   public int i = 10;
   public int x = 30;
   public string str = "Hello";
   public virtual string Hello()
   {
     return "Hello of base class called";
   }
}

I have a child class

public class ChildClass : BaseClass
{
    public int i = 20;
    public int z = 90;
    public override string Hello()
    {
       return "Hello of child class called";
     }
}

Now i have seen that the below code works fine

BaseClass baseObject = new ChildClass();

and when I type baseObject. then i only see members of BaseClass only.

First question: Can someone advise me on a situation where a developer needs to do this BaseClass baseObject = new ChildClass();?

Second question: If my BaseClass object has a reference to my child class object then why are my child member variables not accessible through this baseObject?

+1  A: 
  1. When you want to have objects with individual behavior that have a set of common functions. For example you want to put objects of different types into a list.

  2. The underlying type is still ChildClass but you are currently working on a BaseClass type. That is why you only see the members for BaseClass. It is though still possible to convert the BaseClass instance to a ChildClass instance with a cast operation or the 'as' keyword.

Bernd
+1  A: 

When you do

BaseClass baseObject= new ChildClass();

The static declared type of the object is that of "BaseClass".

Hence you can only see the objects of "BaseClass" type.

If you are sure that the object is of ChildClass Type, you can typecast baseObject to "ChildClass" and then use the ChildClass members

((ChildClass) baseObject). - should help intellisense give you the members of the child class.

Using BaseClass baseObject= new ChildClass(); is the base for RunTime polymorphism. It is very commonly used if you need the overridden child logic to be called but the interface is that of the base class

EDIT : Example of a scenario where you would use it Class User has derived classes called Employee and 3rdPartyUser

Class User has a virtual method called GetRoleInformation - which is used to obtain Role Info for user from the companies Active directory.

However, for 3rd party user, as the information does not exist in AD, the logic for getting the Role Information involves calling a Web Service to retrieve the data. In this case, GetRoleInformation is overridden in 3rdPartyUser class

Now, in the program, on the Login Page, once authenticated, i either get back an object of Employee or 3rdPartyUser. I pass this object to a method with a signature RoleCollection GetRole( User loggedInUser)

Inside this method, without having to determine the type of the user, i just call loggedInUser.GetRoleInformation and depending on whether it is Employee / 3rdPartyUser, the appropriate base / overridden method will be called and Role data will be retrieved from either AD / Web Service.

Long story short :

Advantage of

BaseClass baseObject= new ChildClass();

OVER

ChildClass baseObject= new ChildClass();

is in scenarios when you are not sure of the exact type of child object that is going to be assigned to baseObject variable eg: in this case Employee / 3rdPartyUser Eg:

  BaseClass baseObject= GetLoggedInUser();

where signature of this method is User GetLoggedInUser(string userid)

Otherwise, in an example like yours, where the object is ALWAYS of type "ChildClass", i beleive that there is no advantage to doing it.

InSane
Thanks for the reply, i am aware that its used regularly but i want to know when i should use this in a real time scenerio?
Amit
@Amit -Edited the answer and added a more detailed example. Hope it helps
InSane
Lovely, thanks a lot
Amit
+3  A: 

To answer your first question.

Developers do this to provide abstraction over what actual object they are referring to, which provides flexibility and 'loose-coupling' over the code that uses it.

For example (common scenario - which i use a lot), you might have 10 child classes which extend the base class. What if you wanted a method to return each type of child class? Well, without this type of declaration you would need 10 methods. But if you specified the return type of "BaseClass", you could return all the 10 types of child classes from the one method. This technique ties in closely with the user of interfaces.

E.g

public BaseClass GetDynamicChildClass()
{
     if (someCondition) return ChildClass();
     else if (someOtherCondition) return SomeOtherChildClass();
}

To answer your second question.

You can't see the child properties because you have said "baseObject" is of type "BaseClass" - the compiler has typed the object to this. In order to access the child properties, you need to cast it as the child type:

BaseClass b = new ChildClass();
int x = b.z; // error.
int x = ((ChildClass)b).z; // works - this is a cast, throws exception in bad conversion
ChildClass c = b as ChildClass; // also works, different type of cast, returns null in bad conversion
int x2 = c.z; 

This type of concept (polymorphism) is fundamental to Object-Orientated programming. Have a look at this excellent StackOverflow question: http://stackoverflow.com/questions/210460/try-to-describe-polymorphism-as-easy-as-you-can

It explains it in the simplest way possible, without tying it down to any particular programming framework, which in my opinion is the best way to learn OO.

Hope that helps.

RPM1984
Massive thanks for the reply. that explains well. Cheers
Amit
no worries, happy programming!
RPM1984
+1  A: 

Here is an example where the only method we care about is in the base class. By using this type of abstraction we can easily add more report types.

public class Report
{
    public virtual string ContentType
    {
        get { return "application/octet-stream"; }
    }

    public virtual byte[] Build()
    {
        return new byte[0];
    }

    public static Report Create(ReportType type)
    {
        switch (type)
        {
            case ReportType.Pdf:
                return new PdfReport();
            case ReportType.Html:
                return new HtmlReport();
            case ReportType.Doc:
                return new DocReport();
            case ReportType.Xls:
                return new XlsReport();
            default:
                return new DefaultReport();
        }
    }
}

Then from the client side we only have to do this:

ReportType type = GetReportTypeFromFormPost();
Report report = Report.Create(type);
// ...
Response.Write(report.Build());
ChaosPandion
hmm, be careful not to confuse the OP with the use of abstract classes and the var keyword (without explaining them) - he's learning concrete base/child (for now). He might try and do Report r = new Report(); and not get why it errors.
RPM1984
That's better. =)
RPM1984
A: 

In fact it makes more sense to you, when you use Factory Pattern (http://gsraj.tripod.com/design/creational/factory/factory.html) to instantiate the object. This would abstract out the implementation specific details to different class.

Ravi Gummadi
+1  A: 

The answer of your first questiom : this type of implementation is common when we are using abstract factory patten for the i wll give u a simple example which is creates a family ford car ..

public class AbstractFactoryExample
{
    public AbstractFactoryExample()
    {
        string type = "";
        CarFactory facotry=null;
        if (type == "FORD")
        {
            facotry = new FordCarFactory();
        }
        ICar MyFamilyCar = facotry.CreateFamilyCar();
        ICar MyCityCar = facotry.CreateCityCar();
    }
}
public interface ICar
{

}
public abstract class CarFactory
{
    public  abstract ICar CreateFamilyCar();
    public  abstract ICar CreateCityCar();

}
public class FordCarFactory : CarFactory
{
    public  override ICar  CreateFamilyCar()
    {
        return new FordFamilyCar();
    }
    public override ICar CreateCityCar()
    {
        return new FordCityCar();
    }
}
public class FordFamilyCar : ICar
{

}
public class FordCityCar : ICar
{

}

to your second question :

you are declaring the object as baseclass so it shows only the methods in it only and if you sure about the the generated instance is of type child class

((ChildClass) baseObject) 

can solve the problem

please excuse me for my bad english

Anoop Nadakkara