Can I call a method from a grandparent class, and if so, how?
I'm trying to do something like this:
class A {
void foo() {
// Do something...
}
}
class B : A {
override void foo() {
// Do something else...
}
}
class C : B {
override void foo() {
// Call A's foo method
// Then do something else
}
}
One approach is to use explicit interface implementation in class A:
This allows you to call A's implementation - both from code within C and from outside C (by casting to IBob first).
using System;
namespace ConsoleApp4
{
interface IBob
{
void foo();
}
class A : IBob
{
void IBob.foo()
{
Console.WriteLine("A");
}
public virtual void foo()
{
((IBob)this).foo();
}
}
class B : A
{
public override void foo()
{
Console.WriteLine("B");
}
}
class C : B
{
public override void foo()
{
Console.WriteLine("C");
// Writes B
base.foo();
// Writes A
((IBob)this).foo();
}
}
public class Program
{
static void Main(string[] args)
{
var sally = new C();
sally.foo(); // A B C
IBob sally2 = sally;
sally2.foo(); // A
Console.ReadLine();
}
}
}
Related
In C# I can do this:
public class BaseClass { };
public class A : BaseClass
{
public void Foo(){ Console.WriteLine("A"); }
};
public class B : BaseClass
{
public void Bar(){ Console.WriteLine("B"); }
};
public static void SwitchThingy(BaseClass obj){
Console.WriteLine("Default case");
}
public static void SwitchThingy(A obj){
obj.Foo();
}
public static void Main()
{
A a = new A();
B b = new B();
SwitchThingy(a);
SwitchThingy(b);
}
It will output
A
Default case
However, if I change Main() to
public static void Main()
{
A a = new A();
B b = new B();
List<BaseClass> myList = new List<BaseClass>();
myList.Add(a);
myList.Add(b);
SwitchThingy(myList[0]);
SwitchThingy(myList[0]);
}
Then output changes to
Default case
Default case
Which makes sense since no conversion is required for that overload and so it is preferred over the other which does require extra work.
How can I force the overload for the derived class to be called instead, like in the first case, but after putting the objects into a List?
All I want to avoid here is to have several subclasses (A, B, ...) implementing boilerplate code if possible as well as keep the implementation of SwitchThingy outside of the classes.
As soon as you put the objects in a list of the base class type, the compiler will not any longer be able to help you. Decisions based on the actual type will then have to be made explicitly at runtime in your code.
One possible and classic approach to solve your problem is using the visitor pattern:
This way you only have to implement one "Accept" method in each of your classes. You can then create concrete Visitor classes to decide how to handle the different classes.
class Program
{
public class BaseClass
{
public virtual void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public class A : BaseClass
{
public void Foo() { Console.WriteLine("A"); }
public override void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public class B : BaseClass
{
public void Bar() { Console.WriteLine("B"); }
public override void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public class C : BaseClass
{
public override void Accept(IBaseClassVisitor v)
{
v.Visit(this);
}
};
public interface IBaseClassVisitor
{
void Visit(BaseClass obj);
void Visit(A obj);
void Visit(B obj);
void Visit(C obj);
}
public class SwitchThingyVisitor : IBaseClassVisitor
{
public void Visit(BaseClass obj)
{
Console.WriteLine("Default case");
}
public void Visit(A obj)
{
obj.Foo();
}
public void Visit(B obj)
{
obj.Bar();
}
public void Visit(C obj)
{
// refer to default implementation
Visit((BaseClass)obj);
}
}
public static void Main()
{
A a = new A();
B b = new B();
C c = new C();
List<BaseClass> myList = new List<BaseClass>();
myList.Add(a);
myList.Add(b);
myList.Add(c);
SwitchThingyVisitor visitor = new SwitchThingyVisitor();
foreach (var obj in myList)
{
obj.Accept(visitor);
}
Console.ReadLine();
}
}
A much simpler approach is having a routing function that does an explicit runtime check of the types and calls the respective functions. Newer c# versions allow using a concise syntax by using pattern matching:
class Program
{
public class BaseClass
{
};
public class A : BaseClass
{
public void Foo() { Console.WriteLine("A"); }
};
public class B : BaseClass
{
public void Bar() { Console.WriteLine("B"); }
};
public class C : BaseClass
{
};
public static void RouteSwitchThingy(BaseClass obj)
{
switch (obj)
{
case A a:
SwitchThingy(a);
break;
case B b:
SwitchThingy(b);
break;
default:
SwitchThingy(obj);
break;
}
}
public static void SwitchThingy(BaseClass obj)
{
Console.WriteLine("Default case");
}
public static void SwitchThingy(A obj)
{
obj.Foo();
}
public static void SwitchThingy(B obj)
{
obj.Bar();
}
public static void Main()
{
A a = new A();
B b = new B();
C c = new C();
List<BaseClass> myList = new List<BaseClass>();
myList.Add(a);
myList.Add(b);
myList.Add(c);
foreach (var obj in myList)
{
RouteSwitchThingy(obj);
}
Console.ReadLine();
}
}
Is it possible to use a subset of methods as member methods in different classes in C#?
For instance, I have four functions the void A(), the void B(), the void C() and the void D().
And now I want to have three classes. The first class I would like to have the member methods A, B and C. The second I would like to have the B and D. And the third the A, C and D.
How could I achieve this? Is it possible to achieve this only by using interfaces or are there any other approaches?
If all your three classes should have different implementations for these methods, then classic interfaces are the way to go:
public interface IHaveA {
void A();
}
public interface IHaveB {
void B();
}
public interface IHaveC {
void C();
}
public interface IHaveD {
void D();
}
public class Class1 : IHaveA, IHaveB, IHaveC { // Implement A, B and C here }
public class Class2 : IHaveB, IHaveD { // Implement B and D here }
public class Class3 : IHaveA, IHaveC, IHaveD { // Implement A, C and D here }
If all your classes should have the same implementation of A, B, C and D, you could still use interfaces but you would have to duplicate code:
public static class StaticImplementation {
public void A(IHaveA sender) {
// Do stuff here
}
public void B(IHaveB sender) {
// Do stuff here
}
public void C(IHaveC sender) {
// Do stuff here
}
public void D(IHaveD sender) {
// Do stuff here
}
}
public class Class1 : IHaveA, IHaveB, IHaveC {
public void A() { StaticImplementation.A(this) }
public void B() { StaticImplementation.B(this) }
public void C() { StaticImplementation.C(this) }
}
public class Class2 : IHaveB, IHaveD { // Calls to StaticImplementation for B and D here }
public class Class3 : IHaveA, IHaveC, IHaveD { // Calls to StaticImplementation for A, C and D here }
There is no way to enforce that these three classes have the same implementation of these methods using interfaces, because the primary goal interfaces is to ensure that classes implement methods, specifically with different implementations!
This changes in C# 8.0 and .NET Core 3.0 where you can have default implementations for interface methods, and you could ensure that these implementations do not change by sealing them.
The code would become:
public interface IHaveA {
sealed void A() {
// Implementation here
}
}
public interface IHaveB {
sealed void B() {
// Implementation here
}
}
public interface IHaveC {
sealed void C() {
// Implementation here
}
}
public interface IHaveD {
sealed void D() {
// Implementation here
}
}
public class Class1 : IHaveA, IHaveB, IHaveC { // Nothing to do here }
public class Class2 : IHaveB, IHaveD { // Nothing to do here }
public class Class3 : IHaveA, IHaveC, IHaveD { // Nothing to do here }
using System;
public interface MA {}
public static class MAProvider {
public static void A(this MA obj) { Console.WriteLine("MA"); }
}
public interface MB {}
public static class MBProvider {
public static void B(this MB obj) { Console.WriteLine("MB"); }
}
public interface MC {}
public static class MCProvider {
public static void C(this MC obj) { Console.WriteLine("MC"); }
}
public interface MD {}
public static class MDProvider {
public static void D(this MD obj) { Console.WriteLine("MD"); }
}
public class First : MA, MB, MC {}
public class Second : MB, MD {}
public class Third : MA, MC, MD {}
public static class Program {
public static void Main() {
new First().A();
new First().B();
new First().C();
new Second().B();
new Second().D();
new Third().A();
new Third().C();
new Third().D();
}
}
The only issue which is left is the private members. Since we can not access them inside the extension methods.
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");
}
}
here's what I am trying to do
class A
{
virtual void foo();
}
class B : A
{
virtual override void foo();
}
class C : B
{
override void foo();
}
so what I want to see when calling C.foo() is
A.foo(), B.foo(), C.foo()
but I dont think virtual override can be used in the same function definition. How would I go around this?
Thanks
-Mike
Overridden functions are automatically virtual, unless explicitly declared sealed.
Note that calling C.Foo() will not call B.Foo() or A.Foo() unless C.Foo manually calls base.Foo().
code should work like this:
public class A
{
public virtual void foo() {}
}
public class B : A
{
public override void foo() {}
}
class C : B
{
public override void foo() {}
}
so long as foo is accessible. no need for 'virtual' in B
Is this what you're looking for?
class A
{
public virtual void foo()
{
MessageBox.Show("A");
}
}
class B : A
{
public override void foo()
{
MessageBox.Show("B");
base.foo();
}
}
class C : B
{
public override void foo()
{
MessageBox.Show("C");
base.foo();
}
}
C c = new C();
c.foo();
I have an abstract class A, where I have derived the classes B and C.
Class A provides an abstract method DoJOB(), which is implemented by both derived classes.
There is a class X which has methods inside, which need to call DoJOB().
The class X may not contain any code like B.DoJOB() or C.DoJOB().
Example:
public class X
{
private A foo;
public X(A concrete)
{
foo = concrete;
}
public FunnyMethod()
{
foo.DoJOB();
}
}
While instantiating class X I want to decide which derived class (B or C) must be used.
I thought about passing an instance of B or C using the constructor of X.
X kewl = new X(new C());
kewl.FunnyMethod(); //calls C.DoJOB()
kewl = new X(new B());
kewl.FunnyMethod(); // calls B.DoJOB()
My test showed that declaring a method with a parameter A is not working. Am I missing something?
How can I implement this correctly?
(A is abstract, it cannot be instantiated)
EDIT:
Sorry, I forgot sth.
class A is a generic abstract singleton:
abstract public class A<T> where T : A<T>
{
....
}
public sealed class B : A<B>
{
.....
}
public sealed class C : A<C>
{
.....
}
See the example:
http://www.c-sharpcorner.com/UploadFile/snorrebaard/GenericSingleton11172008110419AM/GenericSingleton.aspx
Under the head line "The solution with the Generic Singleton as an abstract class"
You must have made a mistake in the test, the code works fine:
void Main()
{
X kewl = new X(new C());
kewl.FunnyMethod(); //calls C.DoJOB()
kewl = new X(new B());
kewl.FunnyMethod(); // calls B.DoJOB()
}
public class X
{
private A foo;
public X(A concrete)
{
foo = concrete;
}
public void FunnyMethod()
{
foo.DoJOB();
}
}
public abstract class A
{
public abstract void DoJOB();
}
public class B : A
{
public override void DoJOB()
{
Console.WriteLine("B");
}
}
public class C : A
{
public override void DoJOB()
{
Console.WriteLine("C");
}
}
Outputs :
C
B
For your edit:
void Main()
{
var kewl = new X<C>(new C());
kewl.FunnyMethod(); //calls C.DoJOB()
var kewl2 = new X<B>(new B());
kewl2.FunnyMethod(); // calls B.DoJOB()
}
public class X <T> where T : A<T>
{
private A<T> foo;
public X(A<T> concrete)
{
foo = concrete;
}
public void FunnyMethod()
{
foo.DoJOB();
}
}
public abstract class A<T> where T : A<T>
{
public abstract void DoJOB();
}
public class B : A<B>
{
public override void DoJOB()
{
Console.WriteLine("B");
}
}
public class C : A<C>
{
public override void DoJOB()
{
Console.WriteLine("C");
}
}
Works for me. I get the expected
I did something interesting!
So Did I!
when I run it.
Paste this in your Visual Studio and smoke it
using System;
namespace TestDrive
{
class Program
{
static void Main( string[] args )
{
ServiceConsumer x = new ServiceConsumer( new ConcreteService2() ) ;
x.FunnyMethod() ;
return ;
}
}
abstract class AbstractService
{
public abstract void DoSomethingInteresting() ;
}
class ConcreteService1 : AbstractService
{
public override void DoSomethingInteresting()
{
Console.WriteLine("I did something interesting!");
return ;
}
}
class ConcreteService2 : ConcreteService1
{
public override void DoSomethingInteresting()
{
base.DoSomethingInteresting() ;
Console.WriteLine("So Did I!");
return ;
}
}
class ConcreteService : AbstractService
{
public override void DoSomethingInteresting()
{
Console.WriteLine("Not It's my turn to do something interesting!") ;
return ;
}
}
class ServiceConsumer
{
private AbstractService Service ;
public ServiceConsumer( AbstractService serviceInstance )
{
this.Service = serviceInstance ;
return ;
}
public void FunnyMethod()
{
Service.DoSomethingInteresting() ;
return ;
}
}
}
Cheers!
I'm not sure I understand the question, here is my implementation and it works:
namespace CSharpConsole {
public abstract class A {
public abstract void Test();
}
public class B : A {
public override void Test() {
System.Console.WriteLine("B:Test called!");
}
}
public class C : A {
public override void Test() {
System.Console.WriteLine("C:Test called!");
}
}
class Program {
private A _concrete;
public Program(A concrete) {
_concrete = concrete;
}
public void DoTest() {
_concrete.Test();
}
static void Main(string[] args) {
Program pb = new Program(new B());
pb.DoTest();
Program pc = new Program(new C());
pc.DoTest();
}
}
}