It's a question of overriding in C#.
When I use following code:
class Program
{
class A
{
public virtual void callme()
{
Console.WriteLine("this is A");
}
}
class B : A
{
public new virtual void callme()
{
Console.WriteLine("this is B");
}
}
class C : B
{
public override void callme()
{
Console.WriteLine("this is C");
}
}
static void Main(string[] args)
{
A obj = new C();
obj.callme();
Console.ReadKey();
}
}
OUTPUT: This is A
And when I use:
class Program
{
class A
{
public virtual void callme()
{
Console.WriteLine("This is A.");
}
}
class B : A
{
public override void callme()
{
Console.WriteLine("This is B.");
}
}
class C : B
{
public override void callme()
{
Console.WriteLine("This is C.");
}
}
static void Main(string[] args)
{
A obj = new C();
obj.callme();
Console.ReadKey();
}
}
OUTPUT: This is C.
So if I make a method virtual in the subsequent classes (A as well as B), why it calls the last method, and if the B class is overriding A and C is overriding B then it's calling C's method.
Please explain.
In the 1st case, B is shadowing A and C is overriding the shadow in B. So as long as the reference type is A, it will call the A method.
In the 2nd case B is overriding A and C is overriding B (so it's overriding A).
See: Differences Between Shadowing and Overriding
Check the compiler warning:
Warning 1 '..Program.B.callme()' hides inherited member
'..Program.A.callme()'. To make the current member override that
implementation, add the override keyword. Otherwise add the new
keyword. ..\Program.cs 44 33 Test
It states that method in B hides the method in A. When you override the method in C; it simply overrides the method in B not in A (compiler assumes that you callme in class B is a new method). So when you call A.callme, since the method in A is not overriden, it returns "this is A".
Related
I need to return "this" or the subclass instance from the superclass.
interface IA
{
IA Format();
void Print();
}
interface IB
{
IA Format();
void Print();
void PrintB();
}
abstract class A : IA
{
protected bool isFormated;
public IA Format()
{
isFormated = true;
return this;
}
virtual public void Print()
{
Console.WriteLine("this is A");
}
}
class B : A, IB
{
override public void Print()
{
Console.WriteLine("this is B");
}
public void PrintB()
{
if (isFormated)
{
Console.WriteLine("this is formated B");
}
else
{
Console.WriteLine("this is B");
}
}
}
class Program
{
static void Main(string[] args)
{
var x = new B();
x.Format().PrintB();
}
}
I have two Classes, class A is superclass and class B is the subclass inherited from A.
those two classes implementing Interface A and B.
I need to call 'x.Format().PrintB();' just to format the string.
in other words, I need to return the same object in Format() function and based on the changes in the Format() I need to change the PrintB behavior.
so if I created new Class D and inherits A I want to Implement PrintD with different behavior based on isFormated as well.
I made A as a generic class take type T and I returned this as T
interface IA<T> where T : class
{
T Format { get; }
void Print();
}
abstract class A<T> : IA<T> where T : class
{
protected bool isFormated;
public T Format
{
get
{
isFormated = true;
return this as T;
}
}
virtual public void Print()
{
Console.WriteLine("this is A");
}
}
interface IB
{
void Print();
void PrintB();
}
class B : A<B>, IB
{
override public void Print()
{
Console.WriteLine("this is B");
}
public void PrintB()
{
if (isFormated)
{
Console.WriteLine("this is formated B");
}
else
{
Console.WriteLine("this is B");
}
}
}
class Program
{
static void Main(string[] args)
{
var x = new B();
x.Format.PrintB();
}
}
When you call x.Next(), it returns an instance of something that implements IA. That could be A, B, or any other class that implements IA, but because it returns IA, other classes don't know what the concrete type is. That's usually intentional. If other classes don't know what the implementation of IA is then you can replace one with another.
However, since Next returns an IA, the only way you can call PrintB is if IA has a PrintB method, like this:
public interface IA
{
void PrintB();
}
If A implements IA then it must have a PrintB method. But because it's an abstract class the method can be abstract. That means A doesn't really implement the method. A non-abstract class that inherits from A would be required to implement it.
That would look like this:
abstract class A : IA
{
public IA Next()
{
return this;
}
virtual public void Print()
{
Console.WriteLine("this is A");
}
public abstract void PrintB();
}
PrintB doesn't have to be abstract. A could implement it. It could be virtual and other classes could override it. Or it could be neither abstract nor virtual, and other classes couldn't override it.
Now, when you declare B : A, the compiler will require B to implement PrintB.
Then you can call Next().PrintB() because Next() returns IA and IA has a PrintB method.
I am unable to understand the output. I have following two classes,
class A
{
public int i = 1;
public virtual void Print()
{
Console.WriteLine("I am A");
}
}
class B:A
{
public int i =2 ;
public override void Print()
{
i++;
Console.WriteLine("I am B");
}
}
Now, when i run the following code,
A a1 = new PolymorphismInDepth.B();
a1.Print();
Console.WriteLine(a1.i);
I get the following output,
I am B
1
why do I get 1? Why not 2?
The base class object a1 is pointing to the Derived object in memory. Hence a1.Print() will call the methods reference, i.e., B().Print() but you cannot access B().i using this A().i.
You need to cast it:
Console.WriteLine(((B)a1).i);
You are confused because you used same variable names. Try this out:
class A
{
public int ai = 1;
public virtual void Print()
{
Console.WriteLine("I am A");
}
}
class B : A
{
public int bi = 2;
public override void Print()
{
bi++;
Console.WriteLine("I am B");
}
}
static void Main(string[] args)
{
A a1 = new B();
a1.Print();
Console.WriteLine(a1.ai);
Console.WriteLine(((B)a1).bi);
Console.Read();
}
Trying to access bi like this should give you a compile time error:
Console.WriteLine(a1.bi); //ERROR: 'A' does not contain a definition for 'bi'...
Update:
To add on to the answer - an implementation like this where you override the base class member variable behavior can also be achieved:
class A
{
private int i = 1;
public virtual int I
{
get { return i; }
}
public virtual void Print()
{
Console.WriteLine("I am A");
}
}
class B : A
{
private int i = 2;
public override int I
{
get { return i; }
}
public override void Print()
{
i++;
Console.WriteLine("I am B");
}
}
A a1 = new B();
a1.Print();
Console.WriteLine(a1.I);
Console.WriteLine(((B)a1).I);
Output:
I am B
3
3
In addition to what Sadiq has said. If you mark your classes as public and build you see that editor is indicating something for variable i in class B. It says that you are hiding base member I and should override with new keyword.
So, if you remove public int i =2 ; from class B then you get output as 2 as you are modifying base variable. But if you declare new i in B then you are creating separate scope of new i in B.
So with current code if you put debugger on line Console.WriteLine(a1.ai);
it clearly shows two i variables one with value 1 and other with value 2. Value 2 is for type B. So you will get 2 only when you are referring i from instance of B.
Hope this clears doubt.
Given 2 Types
class A { public virtual void Hello() { Console.WriteLine("A"); } }
class B : A { public override void Hello() { Console.WriteLine("B"); } }
and an instance of 'B'
B b = new B();
Can I access the Hello() method of A thru b ? (I can think of exposing A as property in B but not sure if there is another way)
I knew this is possible in c++ but was scratching my head in c#.
PS:Please no conversations around 'why do you want this?' or 'this is a bad design' etc.
Not from the outside.
From the inside, the instance can call that, via base.Hello(), so you could add a:
public void Foo() { base.Hello(); }
It is not possible in c#. Sorry.
You can try shadowing:
class A { public virtual void Hello() { Console.WriteLine("A"); } }
class B : A { public new void Hello() { Console.WriteLine("B"); } }
Then you can do:
A b = new B();
b.Hello(); //prints A
(B)b).Hello(); //prints B
B b1 = new B();
b1.Hello(); //prints B
Is it possible for the a.doStuff() method to print "B did stuff" without editing the A class? If so, how would I do that?
class Program
{
static void Main(string[] args)
{
A a = new A();
B b = new B();
a.doStuff();
b.doStuff();
Console.ReadLine();
}
}
class A
{
public void doStuff()
{
Console.WriteLine("A did stuff");
}
}
class B : A
{
public void doStuff()
{
Console.WriteLine("B did stuff");
}
}
I'm modding a steam game, Terraria. And I don't want to decompile and recompile it all because that will screw with steam. My program 'injects' into Terraria via XNA. I can use the update() and draw() methods from XNA to mod some things. But it's pretty limited. I wan't to override base methods to mod more things (worldgen for example).
Yes, if you declare doStuff as virtual in A and then override in B.
class A
{
public virtual void doStuff()
{
Console.WriteLine("A did stuff");
}
}
class B : A
{
public override void doStuff()
{
Console.WriteLine("B did stuff");
}
}
Since B is effectively A through inheritance and the method is overloaded.
A a = new B();
a.doStuff();
The code for class A & B you have posted will anyways generate below compiler warning and will ask to use the new keyword on class B, although it will compile:
The keyword new is required on 'B.doStuff()' because it hides inherited member 'A.doStuff()'
Use method hiding along with new and virtual keyword in class Mapper and class B as follows:
class Program
{
static void Main(string[] args)
{
Mapper a = new B(); //notice this line
B b = new B();
a.doStuff();
b.doStuff();
Console.ReadLine();
}
}
class A
{
public void doStuff()
{
Console.WriteLine("A did stuff");
}
}
class Mapper : A
{
new public virtual void doStuff() //notice the new and virtual keywords here which will all to hide or override the base class implementation
{
Console.WriteLine("Mapper did stuff");
}
}
class B : Mapper
{
public override void doStuff()
{
Console.WriteLine("B did stuff");
}
}
Fist of all, I will use virtual and override
for example, base class A has method A.do(), inherited class B has B.do() which overrides A's.
if I call (B as A).do(), which do() would it execute?
or, if there is a method void mymethod(A a) {a.do()}, now I call it by B b; mymethod(b), would it execute b.do()?
The most top override method always will be called, i.e. b.Do() or (b as A).Do() or ((A)b).Do() will call B.Do().
I don't know a way how to call a base method from child class if child class overrides it.
public class A
{
public virtual void Do() { Console.Write("a"); }
public void Do2() { Console.Write("a2"); }
}
public class B : A
{
public override void Do() { Console.Write("b"); }
public new void Do2() { Console.Write("b2"); }
}
class Program
{
static void Main(string[] args)
{
B b = new B();
A a = b;
b.Do(); //b
( b as A ).Do(); //b
a.Do(); //b
( (A)b ).Do(); //b
( b as A ).Do2(); //a2
( (A)b ).Do2(); //a2
( b ).Do2(); //b2
}
}
Output:
b b b b
a2 a2 b2
It entirely depends on whether the do() method was declared virtual or not. If it is not virtual then A.do() is called. If it is virtual then B.do() is called. It is the virtual keyword that enables polymorphism and allows calling a method independent of the type of the reference.
There is no mechanism in C# that allows directly calling a virtual A.do() method from a B object reference. The only exception is using base.do() inside an instance method of class B.
public class A
{
public A() { }
public void Do() { Console.Write("A"); }
}
public class B : A
{
public B() { }
public void Do() { Console.Write("B"); }
}
class Program
{
static void Main(string[] args)
{
B b = new B();
b.Do(); //<-- outputs B
(b as A).Do(); //<-- outputs A
}
}
compiler warns for hiding not overriding:
Warning 1 'ConsoleApplication5.B.Do()' hides inherited member
'ConsoleApplication5.A.Do()'. Use the new keyword if hiding was
intended. c:\Program.cs 18 21 ConsoleApplication5
that is since you are not overriding anything, but simply hiding the method from A.
however
public class A
{
public A() { }
public virtual void Do() { Console.Write("A"); }
}
public class B : A
{
public B() { }
public override void Do() { Console.Write("B"); }
}
calls B twice, when method is overridden.