class Program
{
static void Main(string[] args)
{
List<A> myList = new List<A> {new A(), new B(), new C()};
foreach (var a in myList)
{
Render(a);
}
Console.ReadKey();
}
private static void Render(A o)
{
Console.Write("A");
}
private static void Render(B b)
{
Console.Write("B");
}
private static void Render(C c)
{
Console.Write("C");
}
}
class A
{
}
class B : A
{
}
class C : A
{
}
The output is: AAA
Is it possible to somehow use method overloading, so that the output would be: ABC?
You can use dynamic typing if you're using C# 4:
foreach (dynamic a in myList)
{
Render(a);
}
Within static typing, overload resolution is performed at compile-time, not at execution time.
For the implementation to be chosen at decision time, you either have to use overriding instead of overloading, or use dynamic typing as above.
The following ought to do the trick, where we control the behaviour when working with a type within that type:
class A
{
public virtual void Render()
{
Console.WriteLine("A");
}
}
class B : A
{
public override void Render()
{
Console.WriteLine("B");
}
}
class C : A
{
public override void Render()
{
Console.WriteLine("C");
}
}
static void Main(string[] args)
{
var myList = new List<A> { new A(), new B(), new C() };
foreach (var a in myList)
{
a.Render();
}
Console.ReadKey();
}
And if you want the defined behaviour of a type to be additive to that of its parent, then call the method implemented in the base after executing your own logic, for example:
class B : A
{
public override void Render()
{
Console.WriteLine("B");
base.Render();
}
}
Another way to accomplish this is with the visitor pattern: it allows you to achieve something like polymorphism using a two-way method calling system:
interface IRenderable
{
AcceptForRender(Program renderer);
}
class Program
{
static void Main(string[] args)
{
var p = new Program();
var myList = new List<IRenderable> {new A(), new B(), new C()};
foreach (var a in myList)
{
a.AcceptForRender(p);
}
Console.ReadKey();
}
public void Render(A o)
{
Console.Write("A");
}
public void Render(B b)
{
Console.Write("B");
}
public void Render(C c)
{
Console.Write("C");
}
}
class A : IRenderable
{
public void AcceptForRender(Program renderer)
{
renderer.Render(this);
}
}
class B : IRenderable
{
public void AcceptForRender(Program renderer)
{
renderer.Render(this);
}
}
class C : IRenderable
{
public void AcceptForRender(Program renderer)
{
renderer.Render(this);
}
}
The advantage to this approach is that it allows you to effectively achieve polymorphism (each type ensures the correct overload is called by passing the strongly-typed this to Render internally) while keeping logic that does not belong in your types themselves (e.g., visual rendering logic) out.
Make A B C deriving from a base ( abstract ) class, define in that class a method Render and override properly in each A B C . Instead of calling Render(a) then call a.Render() this is the way polymorfism is supposed to work.
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();
}
}
Here is the code I currently have, the question follows after:
class Program
{
static void Main(string[] args)
{
var obj1 = new A();
obj1.DoIt();
obj1.SetFlyBehavior(new BehaviorB());
obj1.DoIt();
string input = Console.ReadLine();
}
};
class BaseOfA
{
protected ObjectBehavior behavior;
public void DoIt()
{
behavior.DoIt();
}
public void SetBehavior(ObjectBehavior ob) {
behavior = ob;
}
};
class A : BaseOfA {
public A() {
behavior = new BehaviorA();
}
}
interface ObjectBehavior {
void DoIt();
}
class BehaviorA : ObjectBehavior {
void ObjectBehavior.DoIt() {
Console.WriteLine("Behavior: A");
}
}
class BehaviorB : ObjectBehavior {
void ObjectBehavior.DoIt() {
Console.WriteLine("Behavior: B");
}
}
Now my question is, in this case, how am I going to make it work so that I can assign both BehaviorA and BehaviorB to instance obj1 as long as they implement ObjectBehavior?
You are calling obj.SetFlyBehaviour this method is not defined anywhere. The method you define on BaseOfA is called SetBehaviour. Once that is fixed the code you gave compiles fine for me
I'm wondering why in the following example does the base method always get called even though I'm overriding it when the Factory Pattern "Builder" returns a new instance of the object?
interface FactoryInter
{
void MakeDetails();
}
class Builder {
public static Builder getObject(string obj)
{
if(obj == "Cont")
{
return new Cont();
}else{
return new Builder();
}
}
public void MakeDetails()
{
Console.WriteLine("I will always get called..");
}
}
class Cont : Builder, FactoryInter {
public void MakeDetails()
{
Console.WriteLine("Hello..");
}
}
public class Test
{
public static void Main()
{
Builder b = new Builder();
b = Builder.getObject("Cont");
b.MakeDetails();
// your code goes here
}
}
Any help would be greatly appreciated
You do not override it. You are hiding it. Method Cont.MakeDetails() is hiding the base class's MakeDetails method. For more details please see the below example:
class Base
{
public void Hidden()
{
Console.WriteLine("Base!");
}
public virtual void Overrideable()
{
Console.WriteLine("Overridable BASE.");
}
}
class Derived : Base
{
public void Hidden()
{
Console.WriteLine("Derived");
}
public override void Overrideable()
{
Console.WriteLine("Overrideable DERIVED");
}
}
Now testing them yields these results:
var bas = new Base();
var der = new Derived();
bas.Hidden(); //This outputs Base!
der.Hidden(); //This outputs Derived
((Base)der).Hidden();
//The above outputs Base! because you are essentially referencing the hidden method!
//Both the below output Overrideable DERIVED
der.Overrideable();
((Base)der).Overrideable();
To override it, mark the base method as virtual and the derived one as override.
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");
}
}
class Test
{
public delegate void FruitDelegate(Fruit f);
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = del; // Cannot implicitly convert type 'Action<T>' to 'FruitDelegate
}
}
Fruit is an empty class. Both of these delegates have the same signature.
I cannot seem to get any of this working. Maybe it would help if I explained what I am trying to do (provide some context).
I want to create a class that has a generic static method that provides a type and a method callback (like the above example).
The problem I am having is that the delegate contains a parameter and I don't want to have to cast it within the method callback. For example, I want this:
public void SomeMethod()
{
Test.Notify<Apple>(AppleHandler);
}
private void AppleHandler(Apple apple)
{
}
Instead of this:
public void SomeMethod()
{
Test.Notify<Apple>(AppleHandler);
}
private void AppleHandler(Fruit fruit)
{
Apple apple = (Apple)fruit;
}
Is this kind of thing possible?
is this what you want?
static void Main(string[] args)
{
Program p = new Program();
p.SomeMethod();
}
public class Fruit
{ }
public class Apple : Fruit { }
public delegate void FruitDelegate<in T>(T f) where T : Fruit;
class Test
{
public static void Notify<T>(FruitDelegate<T> del)
where T : Fruit, new()
{
T t = new T();
del.DynamicInvoke(t);
}
}
private void AppleHandler(Apple apple)
{
Console.WriteLine(apple.GetType().FullName);
}
public void SomeMethod()
{
FruitDelegate<Apple> del = new FruitDelegate<Apple>(AppleHandler);
Test.Notify<Apple>(del);
}
There is good reason you cannot do this. Suppose the rest of your method was:
class Test
{
public delegate void FruitDelegate(Fruit f);
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = del;
f(new Banana()); //should be legal, but del may be Action<Apple>
}
}
That would definitely not work, so the compiler is correct here.
What about something like this?
public void Notify<T>(Action<T> del) where T : Fruit
{
FruitDelegate f = fruit => del((T)fruit);
}
The FruitDelegate instance, when invoked, would throw an InvalidCastException if, say, an AppleHandler was invoked with a Banana argument.