interface ISpeakerVolume { void Increase(); void ActivateHallEffect(); } abstract class Tablet implements ISpeakerVolume { }
I'm thinking why Java doesn't require the programmer to explicitly state if the methods are not supposed to be implemented in abstract class. While this same intent must be stated explicitly if you are using C#
interface ISpeakerVolume { void Increase(); void ActivateHallEffect(); } abstract class Tablet : ISpeakerVolume { public abstract void Increase(); public abstract void ActivateHallEffect(); }
By the way, if you are wondering why the method declaration signature is not exactly the same as its interface, actually they are not different. interface is just an abstract class with all its methods enforced to be abstract too and public. If such code can be explicitly written (not possible in C#, possible in Java), an interface shall be written like this:
abstract interface ISpeakerVolume { public abstract void Increase(); public abstract void ActivateHallEffect(); } abstract class Tablet implements ISpeakerVolume { public abstract void Increase(); public abstract void ActivateHallEffect(); }
That will compile, interface methods are just abstract methods which doesn't require programmers to explicitly state it as such. And in Java, you can put the abstract keyword before the interface keyword; interface is just an abstract structure, with all its methods enforced to be abstracts too.
So as you can see, on an abstract class you can pass-the-buck the interface methods you don't wish to implement just by exactly repeating the interface method signature, i.e. public abstract void MethodNameHere();
Now, back to why C# didn't mimic the implicitness option of Java, why the need to repeat the interface method's signature if you don't want to implement the interface method in abstract class.
C# can't assume that you just want to pass-the-buck things up when you didn't re-declare the interface methods signature on abstract class. C# wanted you to be conscious of your decision; if you are newcomer to C#, C# allows us to provide different implementations for interface members which has same name and signature.
An example (has compilation errors: abstract class: XXX does not implement interface member YYY) :
interface ISpeakerVolume { void Increase(); void ActivateHallEffect(); } interface ILcdBrightness { void Increase(); void ActivateSepia(); } abstract class Tablet : ISpeakerVolume, ILcdBrightness { }
The abstract Tablet class implements two interfaces which has a method with same name. In C#, you can provide different behaviors for those methods(Increase) with same name, C# cannot just assume that they are the same just because they have the same name. However, if those same method name really have same implementation and you don't want to implement it right there on the abstract class, you can just pass-the-buck things up by repeating the interface signature in the abstract class.
abstract class Tablet : ISpeakerVolume, ILcdBrightness { // repeat all the interface signature in the abstract class // repeating this method signature(and prefixing abstract) makes the two interfaces' Increase method // to only have one behavior on inheriting classes of this abstract class public abstract void Increase(); public abstract void ActivateHallEffect(); public abstract void ActivateSepia(); }
So that's a good conscious decision, you must state your intention to the compiler, compilers can't infer your intentions; because for all we know, those Increase methods might have different behaviors and should be implemented differently. If that is the case, that can be done in C# by explicitly implementing different behaviors for each interface method, the method name is prefixed with the interface name followed by dot then followed by the interface's method name.
abstract class Tablet : ISpeakerVolume, ILcdBrightness { void ISpeakerVolume.Increase() { // behavior goes here } void ILcdBrightness.Increase() { // behavior goes here } public abstract void ActivateHallEffect(); public abstract void ActivateSepia(); }
The need for explicit interface implementation is also apparent if the method name is the same but they have different return type. An example:
interface ISpeakerVolume { void Increase(); void ActivateHallEffect(); } interface ILcdBrightness { int Increase(); void ActivateSepia(); } abstract class Tablet : ISpeakerVolume, ILcdBrightness { // can the compiler infer which of the two Increase should it pass-the-buck? public abstract void ActivateHallEffect(); public abstract void ActivateSepia(); }
ISpeakerVolume has an Increase method which has a void return type, while ILcdBrightness' Increase method has a return type of int. On that scenario, it's more readily apparent why the compiler cannot pass-the-buck the abstract methods implicitly; if the compiler allows such implicitness, what would be the return type of the overriding method on the concrete class then? Compilers can't give preferential treatment to a method based on its return type.
Since C# has explicit interface implementation; you can use it to elegantly pass-the-buck things up for methods with same name, especially if their return types are different.
interface ISpeakerVolume { void Increase(); void ActivateHallEffect(); } interface ILcdBrightness { int Increase(); void ActivateSepia(); } abstract class Tablet : ISpeakerVolume, ILcdBrightness { void ISpeakerVolume.Increase() { IncreaseSpeakerVolume(); } public abstract void IncreaseSpeakerVolume(); int ILcdBrightness.Increase() { return IncreaseLcdBrightness(); } public abstract int IncreaseLcdBrightness(); public abstract void ActivateHallEffect(); public abstract void ActivateSepia(); }
When a concrete class inherit the abstract class Tablet, the concrete class can then make a separate implementation for IncreaseSpeakerVolume and IncreaseLcdBrightness. Neat :-)
This post was originally intended as a bash on C# for not allowing the implementing class to pass-the-buck the interface members by not implementing the interface members, but ended up appreciating C# design choice on forcing the developers to be more explicit with their intent
Actual code:
using System; public class Program { public static void Main() { var t = new Ipad(); ISpeakerVolume s = t; ILcdBrightness l = t; s.Increase(); l.Increase(); s.TurnOn(); l.TurnOn(); } } interface ISpeakerVolume { void Increase(); void TurnOn(); } interface ILcdBrightness { void Increase(); void TurnOn(); } abstract class Tablet : ISpeakerVolume, ILcdBrightness { // C# enforces us to repeat all the interface members on the implementing abstract class or concrete class public void Increase() { Console.WriteLine("Yeah"); } void ISpeakerVolume.TurnOn() { Console.WriteLine("Speaker On"); } void ILcdBrightness.TurnOn() { Console.WriteLine("LCD On"); } } class Ipad : Tablet { }
Output:
Yeah Yeah Speaker On LCD On
No comments:
Post a Comment