I am attempting to override/overload a virtual function that has already been overridden in a base class. To better understand what I want to do please look at the following example:
public class Parent
{
public virtual void foo() {
print("Parent::foo()");
}
}
public class Derived : Parent
{
public override void foo() {
print("Derived::foo()");
}
}
public class Child : Derived
{
public override void foo() {
print("Child::foo()");
}
}
// When I create an instance of Child and call the method foo,
// it calls the Derived::foo() method and not Child::foo()
// How can I make Child override Derived::foo()?
Is it possible to override Derived::foo()? If not how would you suggest I solve this problem?
This calls Child::foo in C#. Try this code:
class Program {
static void Main()
{
Parent foo = new Child();
foo.foo();
}
}
// Define other methods and classes here
public class Parent
{
public virtual void foo() {
Console.WriteLine("Parent::foo()");
}
}
public class Derived : Parent
{
public override void foo() {
Console.WriteLine("Derived::foo()");
}
}
public class Child : Derived
{
public override void foo() {
Console.WriteLine("Child::foo()");
}
}
This will run and print Child::foo().
I can't say for sure without seeing your calling code, but are you sure you didn't make a mistake and create an instance of Derived?
Related
I'm a new developer of c# and I'm using unity3d to develop a game.
I design an interface to implement the skill system in game. But I find some trouble. Here are a lot of Skill classes, and I must call show() method manually inside their apply.
interface ISkill
{
void apply();
}
class Base
{
protected string name { get; set; }
protected void show()
{
Console.WriteLine("show:"+name);
}
}
class Skill1 : Base, ISkill
{
public Skill1()
{
name = "skill1";
}
public void apply()
{
show();
Console.WriteLine("skill1 apply");
}
}
class Skill2 : Base, ISkill
{
public Skill2()
{
name = "skill2";
}
public void apply()
{
show();
Console.WriteLine("skill2 apply");
}
}
Skill3
Skill4
etc..
class Program
{
public static void Main(string[] args)
{
ISkill skill = new Skill2();
skill.apply();
}
}
How to modify my code so that the all SkillX classes can automatically call show() method in apply() method?
Standard solution for this is template method.
Base class implements method as "template" that forces derived classes to provide particular step(s) for that method. In your case the Base class should implement Apply method that calls Show first and than delegates the rest to derived classes by forcing them to provide implementation of the second part via abstract void ApplyImplementation():
interface ISkill
{
void Apply();
}
public abstract class Base
{
protected string name { get; set; }
protected Base(string name)
{
this.name = name;
}
protected void Show()
{
Console.WriteLine("show:"+name);
}
// "template" method.
public void Apply()
{
Show();
ApplyImplementation();
}
// derived class must implement that method
protected abstract void ApplyImplementation();
}
class Skill1 : Base, ISkill
{
public Skill1()
{
name = "skill1";
}
protected override void ApplyImplementation()
{
Console.WriteLine("skill1 apply");
}
}
No general solution, other than trying to pull the commonality across different classes to the base.
In your case, since the only differences among the apply() seems to be the skill name, and you already have it as an instance property, you can pull the apply up to the Base, and have the same implementation across all the child classes of Base.
interface ISkill
{
void apply();
}
class Base : ISkill
{
protected string name { get; set; }
protected Base(string name)
{
this.name = name;
}
public void apply()
{
show();
Console.WriteLine(name + " apply");
}
private void show()
{
Console.WriteLine("show:"+name);
}
}
class Skill1 : Base
{
public Skill1(): base("skill1"){}
}
class Skill2 : Base
{
public Skill2(): base("skill2"){}
}
I want to call a method only once from the base class in a list of classes that all of them derived from base, how can I call method in the base class only once?
public class Base
{
public virtual void foo()
{
Debug.WriteLine("Base foo()");
}
}
public class A : Base
{
public override void foo()
{
base.foo();
Debug.WriteLine("A foo()");
}
}
public class B : Base
{
public override void foo()
{
base.foo();
Debug.WriteLine("B foo()");
}
}
class Program
{
static void Main(string[] args)
{
List<Base> list = new List<Base>();
list.Add(new A());
list.Add(new B());
list.Add(new A());
foreach (Base item in list)
{
item.foo();
}
}
}
instead of :
Base foo()
A foo()
Base foo()
B foo()
Base foo()
A foo()
I want the following result:
Base foo()
A foo()
B foo()
A foo()
Seems like a nonsensical requirement that breaks SoS. To answer your question though you would need a static member boolean in the base class that is flagged as soon as the base method is called.
public class Base
{
// is not thread safe
protected static bool isFooCalled;
public virtual void foo()
{
if(isFooCalled)
return;
Debug.WriteLine("Base foo()");
isFooCalled = true;
}
public static void Reset()
{
isFooCalled = false;
}
}
If you do not even want the method to be entered you would have to add the check in each derived class as well.
public class A : Base
{
public override void foo()
{
if(!Base.isFooCalled)
base.foo();
Debug.WriteLine("A foo()");
}
}
Add a static flag in the base, and adjust the flag
public class Base
{
public Base()
{
if (_instance == null)
_instance = this;//record the first instance
}
static Base _instance;
public virtual void foo()
{
if (_instance == this)
Debug.WriteLine("Base foo()");
}
}
If you want to execute some logic only once then add a static constructor in the base class and move the base::foo logic to this static constructor
static Base()
{
// Move the Base::foo logic here
}
This may not be the answer to your question but may meet your requirement.
I've found in the Troelsen's book, that operator sealed can be used on the members of the class to protect virtual methods from the override.
But if I don't want to override a virtual methods, what sense to make it virtual?
You might have a situation like this:
public class A
{
public virtual void MyMethod()
{
//...
}
}
public class B : A
{
public override void MyMethod()
{
//...
}
}
public class C : B
{
public override void MyMethod()
{
//...
}
}
But what if you want for the inheriting class C NOT to be able to override B's MyMethod, while still allowing B to override A's? Then you can do:
public class B : A
{
public sealed override void MyMethod()
{
//...
}
}
With this change made, you can no longer override the method in C.
In this context, consider the following example:
public class A
{
public virtual void SomeMethod() { }
}
public class B : A
{
public sealed override void SomeMethod() { }
}
public class C : B
{
public override void SomeMethod() { }
}
In this example, without the use of the sealed keyword on SomeMethod in class B, class C would be able to override it because it's original declaration was as virtual. The sealed keyword in this context generates a compiler error. See the MSDN for more information.
the code below is saying a() cannot override a() as wee.a() is not marked virtual, abstract or override. Is there a a way around this? I need to have code inside the super method, but still want to override it!
public abstract class wee
{
public void a()
{
}
}
public class dee : wee
{
public override void a()
{
}
public void b()
{
}
}
You need to mark wee.a virtual or abstract.
Virtual:
public abstract class wee
{
public virtual void a()
{
}
}
public class dee : wee
{
public override void a()
{
}
public void b()
{
}
}
Abstract:
public abstract class wee
{
public abstract void a();
}
public class dee : wee
{
public override void a()
{
}
public void b()
{
}
}
It will not override the method, there is no way to do this without marking the base as such. If you don't want to modify the base as others have suggested, instead you can hide the base method like this:
public class dee : wee
{
public new void a()
{
}
public void b()
{
}
}
Mark wee.a() as virtual -- it allows you to provide a base implementation but gives the option to override that behavior in subclasses if needed.
// wee
public virtual void a() { // do stuff for base implementation }
// dee
public override void a() { // override behavior implemenation }
I want to create a class that can only be inherited, for that i know it should be made abstract. But now the problem is that i want to use functions of that class without making them static. How can i do that.
public abstract Class A
{
A()
{}
public void display()
{}
}
public Class B:A
{
base.A() // this is accessible
this.display() // this is not accessible if i dont make this function static above
}
Your example will not compile, you could consider something like this:
using System;
public abstract class A
{
protected A()
{
Console.WriteLine("Constructor A() called");
}
public void Display()
{
Console.WriteLine("A.Display() called");
}
}
public class B:A
{
public void UseDisplay()
{
Display();
}
}
public class Program
{
static void Main()
{
B b = new B();
b.UseDisplay();
Console.ReadLine();
}
}
Output:
Constructor A() called
A.Display() called
Note: Creating a new B() implicitly calls A(); I had to make the constructor of A protected to prevent this error:
"'A.A()' is inaccessible due to its protection level"
That's not true. You don't have to make Display() static; you can call it freely from the subclass. On the other hand, you can't call the constructor like that.
Maybe it's just an error in the example, but the real issue with the code you have is that you can't put method calls in the middle of your class definition.
Try this:
public abstract class A
{
public void Display(){}
}
public class B:A
{
public void SomethingThatCallsDisplay()
{
Display();
}
}
Here's how you can do this..
public abstract class A
{
public virtual void display() { }
}
public class B : A
{
public override void display()
{
base.display();
}
public void someothermethod()
{
this.display();
}
}