A `class` with only `abstract` methods and no inheritable behavior should be converted to an https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/[`interface`].

== Why is this an issue?

The purpose of an https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members[`abstract` class] is to provide some overridable behaviors while also defining methods that are required to be implemented by sub-classes.

A class that contains only `abstract` methods, often called pure abstract class, is effectively an interface, but with the disadvantage of not being able to be implemented by multiple classes.

Using interfaces over pure abstract classes presents multiple advantages:

* https://en.wikipedia.org/wiki/Multiple_inheritance[**Multiple Inheritance**]: Unlike classes, an interface doesn't count towards the single inheritance limit in C#. This means a class can implement multiple interfaces, which can be useful when you need to define behavior that can be shared across multiple classes.
* https://en.wikipedia.org/wiki/Loose_coupling#In_programming[**Loose Coupling**]: Interfaces provide a way to achieve loose coupling between classes. This is because an interface only specifies what methods a class must have, but not how they are implemented. This makes it easier to swap out implementations without changing the code that uses them.
* https://en.wikipedia.org/wiki/Polymorphism_(computer_science)[**Polymorphism**]: Interfaces allow you to use polymorphism, which means you can use an interface type to refer to any object that implements that interface. This can be useful when you want to write code that can work with any class that implements a certain interface, _without knowing what the actual class is_.
* https://en.wikipedia.org/wiki/Design_by_contract[**Design by contract**]: Interfaces provide a clear contract of what a class should do, without specifying how it should do it. This makes it easier to understand the intended behavior of a class, and to ensure that different implementations of an interface are consistent with each other.

=== Exceptions

`abstract` classes that contain non-abstract methods, in addition to `abstract` ones, cannot easily be converted to interfaces, and are not the subject of this rule:

[source,csharp]
----
public abstract class Lamp // Compliant: Glow is abstract, but FlipSwitch is not
{
  private bool switchLamp = false;

  public abstract void Glow();

  public void FlipSwitch()
  {
    switchLamp = !switchLamp;
    if (switchLamp)
    {
      Glow();
    }
  }
}
----

Notice that, since C# 8.0, you can also define https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods[default implementations for interface methods], which is yet another reason to prefer interfaces over abstract classes when you don't need to provide any inheritable behavior.

However, interfaces cannot have fields (such as `switchLamp` in the example above), and that remains true even in C# 8.0 and upwards. This can be a valid reason to still prefer an abstract class over an interface.

== How to fix it

Convert the `abstract` class to an `interface` with the same methods.

=== Code examples

==== Noncompliant code example

[source,csharp,diff-id=1,diff-type=noncompliant]
----
public abstract class Animal // Noncompliant: should be an interface
{
  public abstract void Move();
  public abstract void Feed();
}
----

=== Compliant solution

[source,csharp,diff-id=1,diff-type=compliant]
----
public interface Animal
{
  void Move();
  void Feed();
}
----

== Resources

=== Documentation

* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/abstract-and-sealed-classes-and-class-members[Abstract and Sealed Classes and Class Members (C# Programming Guide)]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/[Interfaces - define behavior for multiple types]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-8.0/default-interface-methods[Default Interface Methods]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/advanced-topics/interface-implementation/default-interface-methods-versions[Tutorial: Update interfaces with default interface methods]
* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/object-oriented/inheritance[Inheritance - derive types to create more specialized behavior]
* Wikipedia - https://en.wikipedia.org/wiki/Multiple_inheritance[Multiple Inheritance]
* Wikipedia - https://en.wikipedia.org/wiki/Loose_coupling#In_programming[Loose Coupling - In programming]
* Wikipedia - https://en.wikipedia.org/wiki/Polymorphism_(computer_science)[Polymorphism (computer science)]
* Wikipedia - https://en.wikipedia.org/wiki/Design_by_contract[Design by contract]

ifdef::env-github,rspecator-view[]

'''
== Implementation Specification
(visible only on this page)

=== Message

Convert this "abstract" (class|record) to an interface.

=== Highlighting

The identifier of the "abstract" class.

'''
== Comments And Links
(visible only on this page)

include::../comments-and-links.adoc[]

endif::env-github,rspecator-view[]
