Xinus
Xinus

Reputation: 63

Why would I put a reference of class2 into an object of class1?

Ok, so I've come across this code snippet:

class1 a = new class1();
a.Test();

class1 b = new class2();
b.Test();

It had something to do with virtual and override, but my question now is: Why type

class1 b = new class2();

when you could just type

class2 b = new class2();

because both solutions have the same output

Upvotes: 6

Views: 6178

Answers (8)

Yuva Basavoju
Yuva Basavoju

Reputation: 1

I can explain the situation in Java, The same can be applicable in C#

From the below Code, I have created an Object (obj) referencing World class.

Since World extends both India & Belgium classes, We can make use of same Object (obj) in accessing methods of both the Classes, This kind of notation is to improve Efficiency in the code. It is not Mandatory either to follow the same Notation.

Hope I have answered your question, Let me know in case of any concerns :)

class World {

public void printName() {

    System.out.println("Name is: World");
}

}

class India extends World {

public void printName() {

    System.out.println("Name is: India");
}

} class Belgium extends World {

public void printName() {

    System.out.println("Name is: Belgium");
}

} public class Geography {

public static void main(String[] args){

    World obj; // Declaring an Object referencing World Super Class

    obj = new India(); // Allocating M/m to India class (All V & M Ind & World Class)

    obj.printName();

    // Allocating Same Object M/m to Belgium class (All V & M BGM & World Class)

    obj = new Belgium();

    obj.printName();
}

}

Upvotes: 0

JacquesB
JacquesB

Reputation: 42689

It is a question of abstraction and loose coupling. If the code only depends on the type of 'class1' and not the particulars of 'class2' (which is a specific subclass of class1), then the code is more general, and you can easily switch to a different subtype of class1 without changing other code.

An example: Say you have an abstract List class. It has two subclasses, ArrayList and LinkedList. They work more or less the same (as a list of items) but are implemented differently giving them different performance characteristics. When you write your code, you are not sure which implementation is most appropriate for your code. So you want to write your code in such a way that you don't depend on the particulars of any of the specific subclasses.

If your code only cares that the class is a List, then you would only need to name the concrete subclass once:

List x = new LinkedList();

Everywhere else, you can treat it as the more general List class. This ensures two things:

  • If you decide to use ArrayList insted of LinkedList, you only need to change code in one place.
  • You don't accidentally come to depend on implementation specific details of one of the concrete subclasses, e.g. by calling a method which only exist on one of them. By casting to the base class, the type checker ensures that you only can call methods shared by all subclasses. Which again means you can easier swap implementation.

For example, List will define some methods and properties like say Count and Item, which will then be supported by all subclasses. But the specific subclasses might also define additional methods, like say Resize for ArrayList and IsCircular for LinkedList, which only makes sense for the specific subclass.

By declaring the variable as the more general type, List, you ensure that you don't come to depend on some of the subclass-specific methods or properties, since the compiler will simple not let you use them.

Upvotes: 1

tuespetre
tuespetre

Reputation: 1887

A derived class using the "new" keyword on a method instead of "override" will behave differently depending on how it is cast.

Example:

class Class1
{
    public virtual void DoSomething
    {
        Console.WriteLine("Class1.DoSomething");
    }
}

class Class2 : Class1
{
    public new void DoSomething
    {
        Console.WriteLine("Class2.DoSomething");
    }
}

class Class3 : Class1
{
    public override void DoSomething
    {
        Console.WriteLine("Class3.DoSomething");
    }
}

Classes 2 and 3 derive from class 1, but class 2 uses the 'new' keyword to 'hide' the virtual member of class 1, while class 3 uses the 'override' keyword to 'override' the virtual member of class 1. Here is what happens when you use these classes under the guise of their own types:

Class1 one = new Class1();
one.DoSomething(); // outputs "Class1.DoSomething"
Class2 two = new Class2();
two.DoSomething(); // outputs "Class2.DoSomething"
Class3 three = new Class3();
three.DoSomething(); // outputs "Class3.DoSomething"

They all output the right class name, as expected. But this is what happens when you use these classes under the guise of class 1:

Class1 one = new Class1();
one.DoSomething(); // outputs "Class1.DoSomething"
Class1 two = new Class2();
two.DoSomething(); // outputs "Class1.DoSomething"
Class1 three = new Class3();
three.DoSomething(); // outputs "Class3.DoSomething"

Because class 2 'hides' the method, it will output 'Class2.DoSomething' when used as its own type, but it will output 'Class1.DoSomething' when used as its base type. But because class 3 'overrides' the method, it will output 'Class3.DoSomething' whether it is used as its own type or the base type -- because it 'overrides' the base type's functionality.

(The other effect of this is that if Class2 or Class3 have an additional method, say DoSomethingElse, you won't be able to call Class1 two = new Class2(); two.DoSomethingElse() because Class1 does not have that method.)

I don't know of any real-world use cases for this, but it's there, and it's the only way I can think of that using Class1 class2 = new Class2() would offer any real use. If Class2 does not 'hide' any members of Class1, then there is no real benefit.

See: http://msdn.microsoft.com/en-us/library/ms173153.aspx

Upvotes: 2

usr
usr

Reputation: 171216

I'll add another answer to address the question why someone, in his right mind, would have typed it exactly like that.

The only case where this might behave differently is if class2 and class1 both have a method with the same name, but do not use virtual inheritance. This can be done with the new keyword (or no keyword at all which will compile but trigger a well-deserved warning).

This is bad style and almost never useful. That is probably not what he intended.

It might still make sense to write it that way to document the fact that only members of class1 are being used. He might be saying that the fact that it really is a class2 at runtime does not play a role. This is most likely because of virtual inheritance.

So this might be purely for documentation of intent.

Upvotes: 0

kul_mi
kul_mi

Reputation: 1151

You can use this example of instatiating in the "Factory" pattern. That is the first usage which I can think of.

Upvotes: -1

usr
usr

Reputation: 171216

Lets say, B1 and B2 both derive from A. Then you might not know until runtime whether you have a B1 or a B2. In that case you must statically generalize to A which can accommodate both subtypes. If inheritance is used correctly you don't care what the concrete runtime type is.

Example:

A a = GetA();

A GetA() {
 if (Random()) return new B1();
 else return new B2();
}

Because it can be both B1 and B2, you must use a common base class for the variable type (A).

Upvotes: 1

8192K
8192K

Reputation: 5290

class1 is obviously a super class of class2. That way you can for instance have a list of class1 objects, all containing either class1 or class2 objects. You could simply add a and b to that list without problems.

class Class1 {
   public virtual void test(){
       //do something
   {
}

class Class2 : Class1 {
   public override void test(){
      // do something else
   }
}

IList<Class1> list = new List<Class1>();
Class1 a = new Class1();
Class1 b = new Class2();
list.add(a);
list.add(b);

Then, trying to get an item from that list, you can simply do:

list[0].test(); //calls test of Class1
list[1].test(); //calls test of Class2

That concept is called polymorphism (poly=many, morph=shape).

Upvotes: 2

Tzach
Tzach

Reputation: 13396

This is called Polymorphism. In short, it allows you to create multiple subclasses and treat them as they were the parent class, this has some advantages like preventing code duplication.

Upvotes: 0

Related Questions