An interface in C# can only implement abstract methods, methods that are defined but not implemented. However, in C# 8.0 onward, interfaces can provide an implementation for the method defined in them, which is known as the default implementation.
An interface in C# is like an abstract class, as all methods declared inside the interface are abstract methods. Therefore, this allows multiple inheritances to be achieved by a class (meaning a class can inherit or implement multiple interfaces).
However, once an interface is defined and is being used in several classes in a program, changing the interface is quite troublesome. This is because if another method is added inside an existing interface, all the classes that are implementing that interface must implement the new method as well; if not, the program will break.
Hence, in C# 8.0, the default interface method is introduced. This allows the interfaces to not only provide a definition for the method, but also its implementation inside the interface. Therefore, if a class does not implement a method, the default implementation provided in the interface will be used instead, preventing the program from breaking.
public interface IDrawable {void draw();}public class Square : IDrawable {public void draw() {System.Console.WriteLine("A square is drawn.");}}public class Rectangle : IDrawable {public void draw() {System.Console.WriteLine("A rectangle is drawn.");}}class Program {static void Main() {Square s = new Square();Rectangle r = new Rectangle();s.draw();r.draw();}}
In the example above, an interface IDrawable
is declared that defines a void draw()
method. Two classes, Square
and Rectangle
, implement this IDrawable
interface. Both classes provide their own implementation for the void draw()
method. The Square
class instance prints A square is drawn.
and the Rectangle
class instance prints A rectangle is drawn.
Now, we want to introduce a new method void reDraw()
in the IDrawable
interface. The following code snippet provides an example:
public interface IDrawable {void draw();public void reDraw() {System.Console.WriteLine("A shape is re-drawn.");}}public class Square : IDrawable {public void draw() {System.Console.WriteLine("A square is drawn.");}public void reDraw() {System.Console.WriteLine("A square is re-drawn.");}}public class Rectangle : IDrawable {public void draw() {System.Console.WriteLine("A rectangle is drawn.");}}class Program {static void Main() {Square s = new Square();Rectangle r = new Rectangle();s.draw();r.draw();s.reDraw();r.reDraw();}}
Output:
A square is drawn.
A rectangle is drawn.
A square is re-drawn.
A shape is re-drawn.
In the example above, we provide an implementation for the reDraw
method in the Square
class but not the Rectangle
class. Moreover, we also call the reDraw
method on instances of both these classes.
In this case, the program should crash because the Rectangle
class has not provided the implementation for the reDraw
function. However, since we provide a default implementation in the IDrawable
interface, that gets executed and prevents the program from breaking.
Free Resources