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

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");
}

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# Object oriented proggramming issue - overriding methods

Consider this code in C#:
public class A
{
public A()
{
Console.WriteLine("A");
}
public virtual void One()
{
Console.WriteLine("One of A");
}
public virtual void Two()
{
One();
}
}
public class B : A
{
public B()
{
Console.WriteLine("B");
}
public override void One()
{
Console.WriteLine("One of B");
}
public override void Two()
{
Console.WriteLine("Two of B");
}
public void Three()
{
base.Two();
}
}
and the main:
A a3 = new B(); //"A" and then "B"
a3.Two();' //"Two of B"
((B)a3).Three(); //"One of B"
Why does the last line in the main program writes 'One of B'?
Why when it executes One() it goes to the One() of B?
Break down what each method calls -
((B)a3).Three();
calls
B.Three();
which calls
A.Two();
which calls
A.One();
but A.One is virtual, which means that the system has to look at the actual type of the object at runtime to determine which One will be called.
Since the object referenced by a3 is a B (even though you declared it as an A variable reference), B.One() is called.
Because your variable a3 is type B, and because type A's Two method is marked as virtual, the compiler infers that the method that should be called is type B's overridden implementation of One().
Because method One() of class A is declared virtual and it finds an override in class B, so it picks the override.

Why this difference of handling method ambiguity in Java & c#? [duplicate]

This question already has answers here:
Why does Java and C# differ in oops?
(2 answers)
Closed 9 years ago.
I have two classes A & B, where B is derived from A.
Both the classes have a method with same signature. They are called in the following manner in Java & c#-->
In case of JAVA :
class A
{
public void print()
{
System.out.println("Inside Parent");
}
}
class B extends A
{
public void print()
{
System.out.println("Inside Child");
}
}
class test4
{
public static void main(String args[])
{
B b1=new B();
b1.print();
A a1=new B();
a1.print();
}
}
This program generates the following output:-
Inside Child
Inside Child
In case of C# :
class A
{
public void print()
{
System.Console.WriteLine("Inside Parent");
}
}
class B : A
{
public void print()
{
System.Console.WriteLine("Inside Child");
}
}
class Program
{
public static void Main(string[] args)
{
B b1=new B();
b1.print();
A a1=new B();
a1.print();
System.Console.Read();
}
}
This program generates the following output:-
Inside Child
Inside Parent
Why does the output differ ?
In Java, methods are virtual by default.
In C#, methods are not virtual by default.
So, in order for the C# code to behave the same as the Java code, make the method virtual in the base class and override in the derived class.
Or, in order for the Java code to behave the same as the C# code, make the method final in the base class.
In case of c# you need to make the parent method as virtual and child method as an override
class A
{
public virtual void print()
{
System.Console.WriteLine("Inside Parent");
}
}
class B : A
{
public override void print()
{
System.Console.WriteLine("Inside Child");
}
}
class Program
{
public static void Main(string[] args)
{
B b1=new B();
b1.print();
A a1=new B();
a1.print();
System.Console.Read();
}
}
This line:
A a1=new B();
I think here, in C# you have an example of method hiding. Perhaps you need to explicitly declare the method as overridden (for example in java using the #Override annotation).

Call of overloaded method from generic method issue

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().

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