Calling an overwritten child method from parent class? - c#

I am wondering what would theoretically be the output of this code?
Basically I am overwriting a method in the child class but I am calling that
method in the parent class. I am hoping the output of this would be "Child"
public class Animal {
protected virtual void Activate() {
Debug.Log("Parent");
}
void CallStuff() {
Activate();
}
}
public class Frog : Animal {
override void Activate() {
Debug.Log("Child");
}
}
If I were to have a frog instance frog and call ...
frog.CallStuff();
What would the output be?

Perhaps some examples will explain best:
Let's start with a base class:
public class Parent {
public virtual string WhatAmI() {
return "Parent";
}
public string Output() {
return this.WhatAmI();
}
}
Calling the Output method will, of course, give you "Parent"
new Parent().Output(); // "Parent"
Now let's override that virtual method
public class OverridingChild : Parent {
public override string WhatAmI() {
return "Child";
}
Now when you call Output(), it returns "Child"
new OverridingChild().Output(); // "Child"
And if you cast it to a Parent, you get the same result:
((Parent) new OverridingChild()).Output(); // "Child"
If you want the base class's value, you have to call base from within the inheriting class:
public class OverridingChild : Parent {
public override string WhatAmI() {
return "Child";
public string OutputBase() {
return base.WhatAmI();
}
}
new OverridingChild().OutputBase(); // "Parent"
Now for the confusing bit - here's how you can get either value, depending on what class the compiler thinks the object is:
public class NewMethodChild : Parent {
// note that "new" keyword
public new string WhatAmI() {
return "Child";
}
Calling the method directly when the compiler thinks it's the inheriting class gets you the expected result:
new NewMethodChild().WhatAmI(); // "Child"
But if you cast it to the base class, you get the Parent result:
((Parent) new NewMethodChild()).WhatAmI(); // "Parent"
And if you call the Output method, because it is defined at the Parent class it doesn't see the new WhatAmI method of the inheriting class, so it also outputs the base value:
new NewMethodChild().Output(); // "Parent"
Hope that clears things up.

the output would be "Child" It inherited the Call Stuff function but overrode the Activate function so you'd get Child

Related

Constructor in C#

I have a parent class with 2 constructor and the derived class trying to call the constructor of parent in 2 different methods
public class Parent
{
public Parent()
{
//some stuffs
}
public Parent(string st)
{
//some stuffs
}
}
Now I have a derived class with two methods.
I Have to use Parent-constructor in one method and the Parent(string st) in other method.
But here It is always calling the Parent-constructor. Below is the derived class
public class Derived : Parent
{
public void GetData()
{
//Here I initialize the constructor like this
Parent p = new Parent();
}
public void GetData1()
{
string s = "1";
Parent p = new Parent(s);
}
}
Please let me how to make this happen.
Thanks in advance.
Just have two constructors in your Derived class that use the appropriate constructor in the base.
public class Derived : Parent
{
public Derived() : base()
{
}
public Derived(string s) : base(s)
{
}
}
The :base() nomenclature will invoke the parent constructor.
Use the parent constructor call "base"
public class Parent {
public Parent() {}
public Parent(string s) {}
}
public class Child : Parents {
public Child():base() // Call Parent empty constructor
public Child(string s): base(s) // Call Parent Constructor with parameter
}
Your error comes because you're instanciate a new Object Parents in your Child.
With Base(), you call the parent constructor without instanciate him.
Calling new Derived() will call the Parent() ctor because it inherits from Parent and has an implicit Derived() : base().
After you have constructed Derived() calling the method (not constructor) GetData1() will call the Parent(string st) constructor
These are completely separate routes of constructing parent and it seem you are confusing them
The Parent() constructor is always called because you Derived derives from Parent but doesnt include a constructor, hence a default constructor is created, which calls the parameterless parent constructor.
The call to Parent p = new Parent(s); will call the constructor of Parent that takes a parameter.
If you want to call the parent constructor when creating a Derived object, you have to chain the constructors using base().
public class Derived : Parent
{
public void Derived()
: base()
{
//code
}
public void Derived(string s)
:base(s)
{
//code
}
}

Access derived class from virtual method

Though many questions on this topic exist, I am unable to find (yet) a satisfying solution:
Is it possible (and if yes, how?) to access a derived class from the base virtual method?
Let's imagine I have the following classes:
public class parent_class
{
public virtual string common_method () {
dynamic child = /* something to access the derived class */ ;
if (child == null)
return typeof(parent_class).FullName;
else
return child.GetType().FullName;
}
}
public class child_class1 : parent_class {}
public class child_class2 : parent_class {}
public class child_class3 : parent_class {}
Is it possible to execute the following code (and getting the correct result)?
parent_class p = new parent_class();
child_class1 c1 = new child_class1();
child_class2 c2 = new child_class2();
child_class3 c3 = new child_class3();
System.Console.WriteLine(p.common_method()); // result: 'parent_class'
System.Console.WriteLine(c1.common_method()); // result: 'child_class1'
System.Console.WriteLine(c2.common_method()); // result: 'child_class2'
System.Console.WriteLine(c3.common_method()); // result: 'child_class3'
EDIT: After reading the comments and replies I have to add the following points:
I have about 300 different "child classes", so overriding is not an option
I do not want to print the derived class' name - It was just an example
#Siamak Ferdos: I tried the this-keyword, but it somehow did not work as I intended.
Yes you can do it by 'this' keyword simply:
public class parent_class
{
public virtual string common_method()
{
//dynamic child = /* something to access the derived class */ ;
if (this.GetType() == typeof(parent_class))
return typeof(parent_class).FullName;
else
return this.GetType().FullName;
}
}
public class child_class1 : parent_class { }
public class child_class2 : parent_class { }
public class child_class3 : parent_class { }
If I understand your question correctly, you want to print the classes full name via a common base class method. At runtime, the actual instantiated type name is what GetType().FullName will produce, not the type of the base class.
This can be tested with a simple example:
void Main()
{
var parent = new Parent();
var child = new Child();
Console.WriteLine(parent.GetName());
Console.WriteLine(child.GetName());
}
public class Parent
{
public string GetName()
{
return this.GetType().FullName;
}
}
public class Child : Parent
{
}
Yields:
UserQuery+Parent
UserQuery+Child
Where UserQuery is the defined namespace.
There is no need for the method to be virtual or overriden in the derived class for this to work.

Knowing child class overriding method of parent class without additional flag

How do I know that a child class is overriding the method of its parent class? Currently I'm using boolean flag which is set false on the parent class, and when a child is overriding it, the child must set the flag. While it is working, I wonder if there is cleaner solution for this problem.
// The parent class
public Class_A
{
protected bool _hasCheckData = false;
public bool HasCheckData
{
get { return _hasCheckData; }
}
public abstract bool CheckData(File fileToCheck)
{
return true;
}
}
// Lot's of children from class A, this is one of them
public Class_B : Class_A
{
public override bool CheckData(File fileToCheck)
{
// the following line will be duplicated for all Class_A's children
// who implemented the checking of the file. How to avoid this?
_hasCheckData = true;
// checking the file
// and return the result
}
}
public Class_C
{
public void Test(File fileToCheck)
{
Class_B fileAbcChecker = new Class_B();
if (fileAbcChecker.HasCheckData)
fileAbcChecker.CheckData(fileToCheck);
}
}
You can implement a CheckData() that does nothing in Class_A (so it's not abstract anymore). Then, in the relevant Class_B's, override this implementation. In Class_C, remove the if statement. In this way, CheckData() always gets called. By default, it does nothing, unless the class wishes to do something with it.

parent class's constructer in a child class in C#

I have one parent class and one child class.
The parent has a constructor that initializes its parameters.
My question is: How does the child look to the parent's constructor? Can I define a constructor for the children?
you can use base(...) in ctor of your child class.
foreacmple:
public class Child : BaseClass
{
public Child() : base(/*some parameters*/) //CALLING BaseClass parametrized ctor
{
}
}
Just note, if you don't need some specific parameters, just do not do anything, cause BaseClass default ctor will be called by the way when you call ctor of a Child class.
This inheritance sample shows:
how to call the parent constructor from a new constructor on the child
how to pass parameters required by the parent constructor
Code sample:
public class Parent
{
private object _member;
public Parent(object member)
{
this._member = member;
}
}
public class Child : Parent
{
public Child(object member)
: base(member)
{
}
}
You have to define constructors for the children. You can call the base class' constructor using : base() between the constructor prototype and its implementation:
public class Parent {
public Parent() {
...
}
}
public class Child : Parent {
public Child() : base() { // calls Parent.ctor
}
}
Of course.
You are after the "base" keyword.
public class Fruit
{
string TypeOfFruit { get; set; }
public Fruit (string typeOfFruit)
{
TypeOfFruit = typeOfFruit;
}
}
public class Apple : Fruit
{
string AppleType { get; set; }
public Apple(string appleType) : base("Apple")
{
AppleType = appleType;
}
}
You can very well define a constructor for the child class the default one is provided only in case when you do not define a constructor for a class
Meanwhile for how to look up for the constructor of parent
It would check for a parameterless constructor to be present in the parent class and in case you do not have one ( well the compiler lets you know the same) or else you will have to call the parent constructor with the parameters like base("This is the string parameter")
If you meant something else please update the question.

Overriding method to change return type

I have a situation in which I want to override a method of the base class in order to slightly change the return type of the method. By slightly change I mean return an object that inherits from the object that would have been returned by the method in the base type ... actually, a little code would make this easier ...
class Program
{
static void Main(string[] args)
{
var obj = new ParentClass();
Console.WriteLine("Parent says: " + obj.ShowYourHand());
var obj2 = new ChildClass();
Console.WriteLine("Child says: " + obj2.ShowYourHand());
Console.ReadLine();
}
}
public class ParentClass
{
public string ShowYourHand()
{
var obj = GetExternalObject();
return obj.ToString();
}
protected virtual ExternalObject GetExternalObject()
{
return new ExternalObject();
}
}
public class ChildClass : ParentClass
{
protected virtual new ExternalObjectStub GetExternalObject()
{
return new ExternalObjectStub();
}
}
public class ExternalObject
{
public override string ToString()
{
return "ExternalObject";
}
}
public class ExternalObjectStub : ExternalObject
{
public override string ToString()
{
return "ExternalObjectStub";
}
}
The issue I have is that the instance of obj2 doesn't call it's version of GetExternalObject() but rather uses it's parent's implementation.
I think that it is doing so because in the code
var obj = GetExternalObject();
the type of obj is expected to be ExternalObject in the parent class. I understood however that C# cannot distinguish between methods based on return type.
I know there are other solutions to the issue such as defining an IExternalObject so don't get too hung up about that. All I wanted to know was what the thinking is that prevents the child classes GetExternalObject from being called even by the child class itself?
Or am I doing something totally daft? :-)
Or am I doing something totally daft? :-)
Yes, you are. You can't change the return type of a method by overriding it. I don't understand it in your sample anyway. Just leave the return type as it was and return a new ExternalObjectStub. This works, because ExternalObjectStub derives from ExternalObject.
Changing the return type by hiding the base member with new as you do it, is generally a very bad idea, because it leads to a class that can't be used in a polymorphic way. This is exactly what you are experiencing here: If the type of the variable that holds the reference is of type ParentClass it calls the method in ParentClass, even if the instance really is of type ChildClass, because ChildClass doesn't provide an overriden implementation of GetExternalObject.
Polymorphism as you're using it, is not correct. You need to create a new method in your child class that hides the implementation of the base class, with the new return type. You cannot use virtual methods to overload a method like you're doing.
Virtual methods are used to create a different implementation of a method in the child class, not to "overload" it like you're trying to do.
Overloading of methods is done by changing the parameters, not the return type.
So either hide the parent method, in the child class, or create a method with another name. Using virtual for this will not work.
I don't think you're doing anything daft at all. I find myself very frequently looking for ways to implement this same pattern (Class Foo has a Property of type Bar, Class FooSub : Foo should be able to expose that Property as being of type BarSub : Bar).
One important thing to understand about the "new" operator is that it only hides the implementation on the subclass itself. If the subclass is cast back to the base class, the base class's implementation is used instead. So you'll want to make sure you have a "real" method to override so that even when this happens, it's still returning the proper type.
public class ParentClass
{
public string ShowYourHand()
{
var obj = GetExternalObject();
return obj.ToString();
}
protected ExternalObject GetExternalObject()
{
return this.RealGetExternalObject();
}
protected virtual ExternalObject RealGetExternalObject()
{
return new ExternalObject();
}
}
public class ChildClass : ParentClass
{
new protected ExternalObjectStub GetExternalObject()
{
return (ExternalObjectStub)this.RealGetExternalObject();
}
protected override ExternalObject RealGetExternalObject()
{
return new ExternalObjectStub();
}
}
You should have your classes return an interface, with each class (ParentClass and ChildClass) returning an instance of the interface. You should also override the GetExternalObject method in your ChildClass so that the v-table points to the right implementation.
Also, your code had a typo -- your Main method referenced obj twice when you were calling ShowYourHand. I changed that, also, to reference obj and obj2. Here's how you can implement this with an interface (and fixing the obj typo in Main):
class Program
{
static void Main(string[] args)
{
var obj = new ParentClass();
Console.WriteLine("Parent says: " + obj.ShowYourHand());
var obj2 = new ChildClass();
Console.WriteLine("Child says: " + obj2.ShowYourHand());
Console.ReadLine();
}
}
public class ParentClass
{
public string ShowYourHand()
{
var obj = this.GetExternalObject();
return obj.ToString();
}
protected virtual IExternalObject GetExternalObject()
{
return new ExternalObject();
}
}
public class ChildClass : ParentClass
{
protected override IExternalObject GetExternalObject()
{
return new ExternalObjectStub();
}
}
public interface IExternalObject { }
public class ExternalObject : IExternalObject
{
public override string ToString()
{
return "ExternalObject";
}
}
public class ExternalObjectStub : IExternalObject
{
public override string ToString()
{
return "ExternalObjectStub";
}
}
If you want to return ExternalObjectStub in the child class this ExternalObjectStub should derive from ExternalObject class

Categories

Resources