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.
Related
To remove complexity let me explain it using the below code snippet.
I want to call the parent's sum method. Now this code will call recursively and end up in stackoverflow error
public class Program
{
public static void Main()
{
var chd_obj = new child();
chd_obj.x = 10;
chd_obj.y=20;
chd_obj.sum();
}
class parent {
public int x {get;set;}
public int y {get;set;}
public virtual void sum(){
Console.WriteLine("From Base" + x+y);
}
public virtual void DoSum(){
this.sum(); // this should call the sum method in the parent class .
//But it is calling the child *sum* method
}
}
class child:parent {
public override void sum(){
base.DoSum();
}
}
}
I don't know if there is a better solution, but I would declare a private method that both sum in the base class and DoSum in the base class call:
private void SumImpl() {
Console.WriteLine("From Base" + x+y);
}
public virtual void sum(){
SumImpl();
}
public virtual void DoSum(){
SumImpl();
}
You get in infinite loop cause child class call Dosum method in Base class and again Dosum from base call child class that's why you see StackOverflow exception.
you should define what sum you mean to the compiler so the derived class can not be called again from the base class for many times.
static void Main(string[] args)
{
child sample = new child();
sample.x = 20;
sample.y = 15;
sample.sum();
Console.ReadLine();
}
public class parent
{
public int x { get; set; }
public int y { get; set; }
public virtual void sum()
{
Console.WriteLine("From Base " + (x + y));
}
public virtual void DoSum()
{
parent a = new parent();
a.x = this.x;
a.y = this.y;
a.sum();
}
}
class child : parent
{
public override void sum()
{
base.DoSum();
}
}
In this way, there is no need to create new methods but you create new instance from your parent class.
You can't do this in C#. There are workarounds, depending on your actual application.
In general, the solution requires you to extract the base's functionality into one or more non-virtual methods.
private void SumCore()
{
// Do stuff.
}
public virtual void Sum()
{
SumCore();
}
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".
I'm using IoC to define some behavior in my inherited class. I have a property
protected virtual bool UsesThing { get { return true; } }
in my top-level class.
In my inherited class I have
protected override bool UsesThing { get { return false; } }
I'm using the property in my top level class, and it's using the top-level value. Is there a way to make it use the inherited value? I thought that's what virtual was supposed to do.
Code Example:
using System;
public class Program
{
public static void Main()
{
B b = new B();
b.PrintThing();
//I want this to print the value for B
}
public class A
{
protected virtual bool Enabled
{
get
{
return true;
}
}
public void PrintThing()
{
Console.WriteLine(this.Enabled.ToString());
}
}
public class B : A
{
protected override bool Enabled
{
get
{
return false;
}
}
}
}
Here's a Dot Net Fiddle demonstrating my problem
You could do something like this:
https://dotnetfiddle.net/SOiLni
A in of itself knows nothing of B's implementation, so you have to instantiate an object of B in order to access its overriden property.
Slightly modified version of your fiddle:
public class Program
{
public static void Main()
{
A a = new A();
a.PrintThing();
A newA = new B();
newA.PrintThing();
}
public class A
{
protected virtual bool Enabled
{
get
{
return true;
}
}
public void PrintThing()
{
Console.WriteLine(this.Enabled.ToString());
}
}
public class B : A
{
protected override bool Enabled
{
get
{
return false;
}
}
}
}
Given your code example, A's Enabled will be printed, as it should.
When you create an A it knows nothing about B, so polymorphically, you can't expect it to use its value. This makes since, because if you had a class C that also derived from A, it wouldn't know what to use!
On the other hand, if you had written:
public static void Main()
{
A a = new B();
a.PrintThing();
}
You would expect (correctly) that it would use B's override, as you created an instance of that type.
You must have some other issue with your code. This code will print 'true' and 'false' respectively:
public class BaseClass {
public virtual bool DoesSomething {
get {
return true;
}
}
public void Print() {
Console.WriteLine(DoesSomething);
}
}
public class ChildClass : BaseClass {
public override bool DoesSomething {
get {
return false;
}
}
}
Then using these classes:
BaseClass bc = new BaseClass();
bc.Print();
ChildClass sc = new ChildClass();
sc.Print();
If I was to guess you are probably creating instances of the parent class even though your intention is to create instances of the child class.
I want to declare a parent variable, then assign it with a child object
when the parent variable calls a method (exists in both parent / child), it should use the child's version.
public abstract class TowInt
{
public int One;
public int Two;
public char Operator;
public int Result;
public int Remainder;
public void init()
{
calc();
}
protected abstract void calc();
public string getAnswer()
{
return Convert.ToString(Result);
}
public string getQuestion()
{
return string.Format("{0} {1} {2} = ", One, Operator, Two);
}
}
public class TwoIntPlus : TowInt
{
public TwoIntPlus(int one, int two)
{
One = one;
Two = two;
Operator = '+';
}
protected override void calc()
{
Result = One + Two;
}
}
public class TwoIntDivision : TowInt
{
public TwoIntDivision(int one, int two)
{
One = one;
Two = two;
Operator = '/';
}
protected override void calc()
{
Result = One / Two;
Remainder = One % Two;
}
new public virtual string getAnswer()
{
return string.Format("{0}R{1}", Result, Remainder);
}
}
using System.IO;
class ConsoleApplication1
{
static void Main()
{
// For child class, the child method getAnswer() is called
TwoIntDivision n2 = new TwoIntDivision(32, 4);
n2.init();
Console.WriteLine(n2.getQuestion() + n2.getAnswer());
// 32 / 4 = 8R0 -- this is what I expected
// If assign a child object to parent, then the parent method is called
TowInt two;
two = new TwoIntDivision(32, 4);
two.init();
Console.WriteLine(two.getQuestion() + two.getAnswer());
// 32 /4 = 8 -- this is not what I expected
two = new TwoIntPlus(32, 4);
two.init();
Console.WriteLine(two.getQuestion() + two.getAnswer());
Thread.Sleep(5000);
}
}
The problem with your code is that you have not marked the getAnswer method as virtual in the base class.
So, in the TwoIntDivision class you are hiding - not overriding (extending) the base class method:
// this is hiding the base class method, not overriding it (notice the new modifier)
new public virtual string getAnswer()
Then, when you cast your object, depending on the type it will use the method for the type you are working with. This is totally expected behavior and can come in handy in the right context.
To get the behavior you expect, modify your definitions like this:
public abstract class TowInt
{
public virtual string getAnswer() {
return "Hello from Base-Class";
}
}
public class TwoIntDivision : TowInt
{
public override string getAnswer() {
return "Hello from Division";
}
}
TowInt t = new TwoIntDivision();
Console.WriteLine(t.getAnswer()); // prints "Hello from Division"
As a side note, in case you are coming from a Java background, in C# methods are final (non-virtual) by default. If you want to allow a method to be overrideable in a derived class you have to explicitly mark it with the virtual modifier.
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.