Call of overloaded method from generic method issue - c#

I've run into interesting thing (works same in both Java and C#).
Java code:
public class TestStuff {
public static void main(String[] args) {
Printer p = new PrinterImpl();
p.genericPrint(new B());
}
}
class PrinterImpl implements Printer {
void print(A a) {
System.out.println("a");
}
void print(B b) {
System.out.println("b");
}
#Override
public <T extends A> void genericPrint(T b) {
print(b);
}
}
interface Printer {
public <T extends A> void genericPrint(T a);
}
class A {
}
class B extends A{
}
C# code:
namespace TestStuff
{
internal class Program
{
private static void Main(string[] args)
{
var printer = new Printer();
printer.GenericPrint(new B());
}
}
public class Printer
{
public void Print(A a)
{
Console.WriteLine("a");
}
public void Print(B b)
{
Console.WriteLine("b");
}
public void GenericPrint<T>(T a) where T : A
{
Print(a);
}
}
public class B : A
{
}
public class A
{
}
}
When I wrote something like this I expected to see "b" printed in both cases.
But, as you can see, it is "a" what is printed.
I've read C# language specification and it says overloaded method is selected at compile-time. It explains why it works that way.
However, I had no time to check it out in Java language specification.
Could somebody please give a more detailed explanation of what is happening and why? And how could I achieve what I wanted?
Thanks in advance!

The key is to understand that generics are only available at compile time in java. It is just syntax sugar that the compiler uses while compiling, but throws away while generating the class files.
As such, the code:
public <T extends A> void genericPrint(T b) {
print(b);
}
is compiled into:
public void genericPrint(A b) {
print(b);
}
Since the argument to print is of type A, the overloaded version print(A a) is the one resolved. I'd suggest using polymorphic calls on instances of A or the Visitor pattern to callback into PrinterImpl for your use case.
Something like:
interface Visitor {
void visit(A a);
void visit(B b);
}
class PrinterImpl implements Printer, Visitor {
void print(A a) {
System.out.println("a");
}
void print(B b) {
System.out.println("b");
}
public <T extends A> void genericPrint(T b) {
b.accept(this);
}
public void visit(A a) {
print(a);
}
public void visit(B b) {
print(b);
}
}
interface Printer {
public <T extends A> void genericPrint(T a);
}
class A {
public void accept(Visitor v) {
v.visit(this);
}
}
class B extends A {
public void accept(Visitor v) {
v.visit(this);
}
}

Its true that overloaded methods are selected at compile time and its true for java also(dynamic method dispatch).
However Generics works a little differently. Your method GenericPrinter can only work Types A or its derivative. Its a constraint on that method. Suppose in your GenricPrinter class you have invoked a method thats defined in A.
public class A
{
void DoSomethingA()
{
}
}
.
.
.
public void GenericPrint<T>(T a) where T : A
{
//constraint makes sure this is always valid
a.DoSomethingA();
Print(a);
}
So this constraint would make sure that only A or its sub classes, that contains the above method would only be allowed.
Although you pass in an instance of A's subclass but due to constaint, GenericPrinter would treat the subclass as A.
Just remove the constraint part (T:A) and B would be printed as you expect.

There is no runtime check of which type a is in your GenericPrint method. The only thing you enforce with the where T : A part, is that you can call Print.
Btw, apart from that generic method: If you want a to be printed, although it is an instance of B, then you have to declare that variable as A obj = new B().

Related

Exposing only some inherited methods in the derived class

I stumbled across an interview question related to OOPS. Here is the question:
There is a base class A with 5 methods. Now how should I design the class such that if a class B inherits class A, only 3 methods are exposed. And if a class C inherits class A, the rest of the 2 methods are exposed.
Any thoughts ??
if A is partial and you have 2 namespaces then:
namespace the_impossible
{
class Program
{
static void Main(string[] args)
{
B b = new B();
C c = new C();
b.m1();
b.m2();
b.m3();
c.m4();
c.m5();
}
}
namespace A_1
{
public partial class A
{
public void m1() { }
public void m2() { }
public void m3() { }
}
}
namespace A_2
{
public partial class A
{
public void m4() { }
public void m5() { }
}
}
class B : A_1.A
{
}
class C : A_2.A
{
}
}
It should not be possible in any object-oriented language, otherwise it would break the Liskov substitution principle. Substituting a B for an A should not reduce its correctness (meaning methods should not suddenly be unavailable)
However, there is still some ambiguity in the question that allows for some "out-of-the-box" thinking. Here are questions I would pose back to the interviewer:
What do you mean by "exposed"?
Do the 5 methods in A have to be public?
Does the "exposition" by C need to be implicit or can the be explicitly exposed (e.g. pass-through)
Based on those answers you could either come up with possible options using internal, explicit interface implementations, etc.
I think it was a trick or even dumb question. To achieve this, we must break the Liskov substitution principle. You shouldn't preseve the hierarchy of the classes.
Maybe you just should use interfaces instead:
public class A {} //why we even need this class?
public class B : A, I3Methods
{
public void Method1() { }
public void Method2() { }
public void Method3() { }
}
public class C : A, I2Methods
{
public void Method4() { }
public void Method5() { }
}
public interface I3Methods
{
void Method1();
void Method2();
void Method3();
}
public interface I2Methods
{
void Method4();
void Method5();
}
The only way I can think of is to have them all private in A and then expose them through encapsulation in B and C... But they are not exposed, only executed... So it is half right.
I also think that's impossible.
But to give an approximate answer:
Make 3 methods in A virtual, then implement them in B. Then override those 2 methods in C.
Nobody says that the 5 methods of class A should be exposed when writing them. In C# you could simply write 5 protected methods in class A and expose those you wish to be accessible by writing some hiding methods with the new modifier like this - although this wouldn't actually expose the methods directly they are merely wrapped.
class A
{
protected void M1() { }
protected void M2() { }
protected void M3() { }
protected void M4() { }
protected void M5() { }
}
class B : A
{
public new void M1()
{
base.M1();
}
public new void M2()
{
base.M2();
}
public new void M3()
{
base.M3();
}
}
class C : A
{
public new void M4()
{
base.M4();
}
public new void M5()
{
base.M5();
}
}
In your comments, you mentioned that you were interested if this could be done in any other language. You can kind of do it in C++ through the use of the using keyword. So, starting with class A:
class A {
public:
int Method1() { return 1; }
int Method2() { return 2; }
int Method3() { return 3; }
int Method4() { return 4; }
int Method5() { return 5; }
};
Then you define class B, using private inheritance (essentially you can't auto cast from B to A and all public methods in A become private methods in B).
class B: private A {
public:
// We want to expose methods 1,2,3 as public so change their accessibility
// with the using keyword
using A::Method1;
using A::Method2;
using A::Method3;
};
Do the same for class C, exposing the other two methods instead:
class C: private A {
public:
using A::Method4;
using A::Method5;
};
Or if you're supposed to expose all the methods through C, simply use public inheritance and everything exists:
class C: public A {
public:
};
For usage:
B *b = new B();
b->Method1(); // This works, Method1 is public
b->Method4(); // This fails to compile, Method4 is inaccessible
The reason I said kind of above is because you can work around it by explicitly casting the instance of B to an A:
A *brokena = b; // This wouldn't compile because the typecast is inaccessible
A *a = (A*)b; // This however does work because you're explicitly casting
a->Method4(); // And now you can call Method4 on b...
I know, it is to late to respond. Just thought of sharing my thoughts:
Define Class A as a base class.
Have intermediate child classes A1 -> M1,M2,M3 and A2 -> M4, M5 deriving from Class A
Now, you can have
1) Class B inheriting A1
2) Class C inheriting A2
These two classes are still derived from Class A.
And also we are not breaking liskov substitution principle.
Hope, this gives clarity.

C# Restrict which classes can call a method

I want to be able to restrict which classes have access to call a method of another class. I have a the following:
public class A: B
{
private void DoSomething()
{
C.Method1(); // should compile
}
}
public abstract class B
{
}
public class D
{
private void DoSomething()
{
C.Method1(); // shouldn't compile
}
}
public static class C
{
public static void Method1()
{
}
public static void Method2()
{
...
Method1();
...
}
}
All of these classes are in the same assembly, but class B is in a different assembly.
My goal is for class A to be able to call C.Method1, but have class D not able to call C.Method1
I was thinking of making class C a parent class, and have class A inherit class B, but class A already inherits from class B.
Method1 doesn't belong in class A or B.
A practical use for this is when Method1 is a utility method, and should only be called by class A and class C
Without moving methods around, you'd have to make C non-static, make Method1 protected, then have B inherit from C, which would look like:
public class A : B
{
private void DoSomething()
{
C.Method1(); // should compile
}
}
public abstract class B : C
{
}
public class D
{
private void DoSomething()
{
C.Method1(); // shouldn't compile
}
}
public class C
{
protected static void Method1()
{
}
}

How to achieve same override experience in C# as in Java?

Considering the following Java code:
public class overriding {
public static void main(String[] args) {
b b = new b();
a a = (a)b;
a.Info();
b.Info();
}
}
class a {
void Info() {
System.out.println("I'm a");
}
}
class b extends a {
void Info() {
System.out.println("I'm b");
}
}
And now let's try to do the same in C#
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
b b = new b();
a a = (a)b;
a.Info();
b.Info();
Console.ReadLine();
}
}
class a
{
public void Info()
{
Console.WriteLine("I'm a");
}
}
class b : a
{
public void Info()
{
Console.WriteLine("I'm b");
}
}
}
The Java example output
I'm b
I'm b
The C# version output
I'm a
I'm b
Is there a way to implement class b so that it prints "I'm b" twice? Please notice i'm not looking at a way to change a.
In Java, methods are virtual by default. In C# they are not, and you need to use the keywords "virtual" and "override" for the method declarations in classes a and b, respectively.
In C# version, you need to use override keyword in the class b method, and also you need to make the method in class a virtual explicitly. In Java, methods are virtual by default. That's not the case in C#. You need to tell that explicitly:
class a
{
public virtual void Info()
{
Console.WriteLine("I'm a");
}
}
class b : a
{
public override void Info()
{
Console.WriteLine("I'm b");
}
}
No. By design. c# has virtual methods that you may override in subclasses. The idea is, that the possibility for override is part of the classes contract.
In the Java model, a subclass might break behavior by naming a new method the same as a base method but not providing the proper behavior.
In c# you need to be explicit about this.
One major difference between Java and C# is that in Java, methods are virtual by default. To do the same in C#, you need to mark the method a.Info as virtual and then use the override keyword in b:
class a
{
public virtual void Info()
{
Console.WriteLine("I'm a");
}
}
class b : a
{
public override void Info()
{
Console.WriteLine("I'm b");
}
}
UPDATE
You can also use the new keyword on class b without needing the virtual keyword on a:
class a
{
public void Info()
{
Console.WriteLine("I'm a");
}
}
class b : a
{
public new void Info()
{
Console.WriteLine("I'm b");
}
}
However, this will only produce "I'm b" when the object is of type b, but will say "I'm a" when it is cast back to b:
b myB= new b();
myB.Info(); // This will say "I'm b"
a myA = (a)myB;
myA.Info(); // This will say "I'm a" even though it's really a b object.
See MSDN more info
In Java , we are not using any keywords for method overloading and method overriding. While in C#, you have to use override for method overriding explicitly.
public override void Info()
{
Console.WriteLine("I'm b");
}

Calling method based on run-time type insead of compile-time type

In an application, I need .NET to call a method based on its run-time type instead of its compile-time type.
Simplified Example:
class A { }
class B : A { }
static void Main(string[] args)
{
A b = new B();
Print(b);
}
static void Print(A a)
{
Console.WriteLine("Called from A");
}
static void Print(B b)
{
Console.WriteLine("Called from B");
}
The above code will actually print Called from A, but I need it to be Called from B.
This works as expected:
static void Print(A a)
{
var b = a as B;
if (b != null)
return Print(b);
else
Console.WriteLine("Called from A");
}
But for maintainability's sake, it is not desirable.
I believe this question is similar to this one: Why isn't this method chosen based on the runtime-type of its object?, but for .NET instead of Java.
The simplest approach if you're using .NET 4 or higher is to use dynamic typing:
dynamic b = new B();
Print(b);
Almost all expressions using a value of type dynamic will be invoked dynamically, with a "mini-C# compiler" applying the same rules at execution time as it would have done at compile-time, but using the actual execution-time type of those dynamic values. (Expressions whose types are known statically at compile-time will still be regarded as having those types though - it doesn't make everything about overload resolution into dynamic.)
If you're not using .NET 4, it's somewhat harder - you could either use reflection, or hard-code the options, neither of which is fun.
You can make use of the dynamic type:
A b = new B();
dynamic tmp = b;
Print(tmp); // Prints "Called from B"
However, please note that this has the draw back that it will generate a runtime exception instead of a compile error if there is no matching method.
Use overriding of OOP.
Exmaple:
class A {
public virtual void Print() {
Console.WriteLine("Called from A");
}
}
class B : A {
public override void Print() {
Console.WriteLine("Called from B");
}
}
and use it like:
A b = new B();
Print(b);
static void Print(A a)
{
a.Print(); //will run B's method
}
It will run runtime type method, as you use simple overriding concept.
This is not how polymorphism works. You should consider doing something similar to the following instead:
class A
{
virtual string GetString()
{
return "Called from A";
}
}
class B : A
{
override string GetString()
{
return "Called from B";
}
}
static void Main(string[] args)
{
A b = new B();
Print(b);
}
static void Print(A a)
{
Console.WriteLine(a.GetString());
}
try this:
class A
{
public virtual string Print()
{
return "Called from A";
}
}
class B : A
{
public override string Print()
{
return "Called from B";
}
}
And test it elsewhere
A b = new B();
MessageBox.Show(b.Print()); //called from B

Why C# doesn't support base.base?

I tested code like this:
class A
{
public A() { }
public virtual void Test ()
{
Console.WriteLine("I am A!");
}
}
class B : A
{
public B() { }
public override void Test()
{
Console.WriteLine("I am B!");
base.Test();
}
}
class C : B
{
public C() { }
public override void Test()
{
Console.WriteLine("I am C!");
base.base.test(); //I want to display here "I am A"
}
}
And tried to call from C method Test of A class (grandparent's method). But It doesn't work. Please, tell me a way to call a grandparent virtual method.
You can't - because it would violate encapsulation. If class B wants to enforce some sort of invariant (or whatever) on Test it would be pretty grim if class C could just bypass it.
If you find yourself wanting this, you should question your design - perhaps at least one of your inheritance relationships is inappropriate? (I personally try to favour composition over inheritance to start with, but that's a separate discussion.)
One option is to define a new method in B as shown below
class B : A
{
public B() { }
public override void Test()
{
Console.WriteLine("I am B!");
base.Test();
}
protected void TestFromA()
{
base.Test()
}
}
and use TestFromA() in C

Categories

Resources