Reputation: 63
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
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
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:
ArrayList
insted of LinkedList
, you only need to change code in one place.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
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
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
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
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
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
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