4

Consider the following classes:

public class X {};
public class Y : X {};
public class Z : X {};

public class A {
    public bool foo (X bar) { 
        return false;
    }
};

public class B : A { 
    public bool foo (Y bar) { 
       return true;
    }
};    

public class C : A { 
    public bool foo (Z bar) { 
       return true;
    }
};

Is there a way to achieve the following desired output?

A obj1 = new B();
A obj2 = new C();

obj1.foo(new Y()); // This should run class B's implementation and return true
obj1.foo(new Z()); // This should default to class A's implementation and return false

obj2.foo(new Y()); // This should default to class A's implementation and return false
obj2.foo(new Z()); // This should run class C's implementation and return true

The issue I am having is that class A's implementation is always being called regardless of the arguments passed.

2 Answers 2

5

You need to make the foo method in class A virtual so it can be overridden properly and called polymorphically.

public class A { public virtual bool Foo (X bar) { ... } }
public class B { public override bool Foo (X bar) { ... } }

The way you are doing it at the moment, is effectively defining a new method implementation in B and C which will only be called if the instance is of that type. Since you are declaring them as type A (A obj1 = new B();) and the method is not virtual then the A implementation will always be called.

Sign up to request clarification or add additional context in comments.

2 Comments

But then if I call obj1.Foo(new Z()); it would return true. The desired behavior is for it to return false. Class B should not call it's own Foo() unless the argument is of type Y.
This solves your problem properly, you can implement whatever logic you want inside the methods and even call into the base implementation via base.Foo(bar) if you want to pass the decision down.
3

I believe you desire to define virtual method and override it with a signature that contains derived types. That is not possible as the method that overrides the base one should have the same signature. Probably this is because that would require the compiler to apply complex traversal rules. So as suggested in the previous answer to get the desired behavior:

public class A { public virtual bool Foo (X bar) { ... } }
public class B { 
    public override bool Foo (X bar) {
         if(bar is Y) { ... } 
         else base.Foo(bar);
    }
}

2 Comments

Would there be a way to say, cast obj1 as type B to obtain the desired behavior?
@DanBrenner Sure: ((B)obj1).foo(new Y()); should return true as desired. But I image some "sugar" required.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.