Почему у нас есть интерфейсы?
С теоретической точки зрения и реализация интерфейса, и наследование классов решают одну и ту же проблему: они позволяют вам определять отношения подтипов между типами.
Так почему у нас оба в C#? Зачем вообще нужны интерфейсы? Разве мы не можем просто определить интерфейс как абстрактный класс, как мы это делаем, например, в C ++?
Причина этого - проблема ромба : ( Источник изображения )
![enter image description here](https://i.stack.imgur.com/Xy5O0.png)
If both B
and C
implement A.DoSomething()
differently, which implementation should D
inherit? That's a hard problem, and the Java as well as the C# designers decided to avoid it by allowing multiple inheritance only for special base types which do not include any implementation. They decided to call these special base types interfaces.
So, there is no "principle of interface". Interfaces are just a "tool" to solve a particular problem.
So why do we need default implementations?
Backwards compatibility. You wrote a vastly successful library used by thousands of developers worldwide. Your library contains some interface I
, and now you decide that you need an extra method M
on it. The problem is:
- You can't add another method
M
to I
, because that would break existing classes implementing I
(because they don't implement M
), and
- you can't change
I
to an abstract base class, because that, as well, would break existing classes implementing I
, and you will lose the ability to do multiple inheritance.
So how do default implementations avoid the diamond problem?
By not inheriting those default methods (example inspired by the one in эта статья , некоторые интересные угловые случаи см. В полной статье):
interface I1
{
void M() { Console.WriteLine("I1.M"); } // default method
}
interface I2
{
void M() { Console.WriteLine("I2.M"); } // default method
}
class C : I1, I2 { }
class Program
{
static void Main(string[] args)
{
// c, i1 and i2 reference the same object
C c = new C();
I1 i1 = c;
I2 i2 = c;
i1.M(); // prints "I1.M"
i2.M(); // prints "I2.M"
c.M(); // compile error: class 'C' does not contain a member 'M'
}
}