Относится ли реализация по умолчанию членов интерфейса в C# 8 к решению проблемы множественного наследования абстрактного класса?

Я читаю этот блог .NET Engineering Team и они представили новую функцию реализации по умолчанию для Interface, Я запутался в связи с его мотивом, кроме проблемы многоуровневого наследования abstract class, Кроме этого, я не могу понять какую-либо другую выгоду. Создайте следующий код:

C# 7 (невозможно предоставить определения методов)

interface ILogger
{        
    void LogData(dynamic data, dynamic logMode);

    bool SendStatusEmail(string emailAddress);

}
public class EmployeeLog : ILogger
{
    public void LogData(dynamic data, dynamic logMode)
    {
        throw new NotImplementedException();
    }

    public bool SendStatusEmail(string emailAddress)
    {
        throw new NotImplementedException();
    }
}

public abstract class Logger
{
    public abstract void LogData(dynamic data, dynamic logMode);

    public bool SendStatusEmail(string emailAddress)
    {
        // Email Sending Code
        return true;
    }
}

public class EmployeeLog : Logger
{
    public override void LogData(dynamic data, dynamic logMode)
    {
        throw new NotImplementedException();
    }
}

C# 8 (можно предоставить определения методов)

interface ILogger
{
    void LogData(dynamic data, dynamic logMode);

    public bool SendStatusEmail(string emailAddress)
    {
        // Email Sending Code
        return true;
    }

}
public class EmployeeLog : ILogger
{
    public void LogData(dynamic data, dynamic logMode)
    {
        throw new NotImplementedException();
    }
}

public abstract class Logger
{
    public abstract void LogData(dynamic data, dynamic logMode);

    public bool SendStatusEmail(string emailAddress)
    {
        // Email Sending Code
        return true;
    }
}

public class EmployeeLog : Logger
{
    public override void LogData(dynamic data, dynamic logMode)
    {
        throw new NotImplementedException();
    }
}

В C# 8, и то и другое abstract class а также interface может выполнить ту же работу, что и реализация по умолчанию для своих членов. У меня есть следующие сомнения, связанные с этим:

  • Если интерфейс обеспечивает реализацию по умолчанию, а также поддерживает множественное наследование, зачем нуждаться в абстрактном классе в C# 8?

  • Что будет в случае этого сценария?

:

interface ILogger
{
   public bool SendStatusEmail(string emailAddress)
{
    // Email Sending Code
    return true;
  }
}
interface IEmail
{
    public bool SendStatusEmail(string emailAddress)
    {
        // Email Sending Code
        return true;
    }

}

public class EmployeeLog : ILogger, IEmail
{
}

public class Test
{
    EmployeeLog emp = new EmployeeLog();
    emp.SendStatusEmail();  //Which function it will refer to?
}

0 ответов

Ответ: Абстрактные классы могут иметь поля и виртуальные методы.

Вот почему множественное наследование не поддерживается в C# (также в Java).

Поля с множественным наследованием могут вызывать проблемы, когда:

class A : B, C {...}
class C : D {...}
class B : D {...}
class D
{
    ...
    protected int _value;
    ...
}

Если унаследованное B а также C использовать один и тот же экземпляр _value?

И тому и другому есть причины.

Если так, то логика в B а также C могут мешать друг другу, потому что значение _value не предсказуемо для B ни для C.

А также B а также C даже не подозревают, что они будут работать друг с другом как части одного объекта.

Если нет, то какой экземпляр _value должен быть доступен из A?

Аналогичные проблемы применимы и к виртуальным методам. Поскольку виртуальная таблица больше не будет линейной, когда обаB а также C переопределить виртуальный метод, определенный в D.

Их решение сделало бы отношения наследования очень сложными, поэтому Java не поддерживает множественное наследование и ввела концепцию интерфейса, и это также пришло в C#.

Как интерфейс решил эту проблему

В определениях интерфейсов есть только объявления методов (относительно свойств как средств доступа как методов), поэтому не может быть полей и переопределений методов. Таким образом, нет проблем множественного наследования.

Как C# 8.0 может позволить интерфейсам иметь тела методов, не вызывая этих проблем

Реализация по умолчанию в C# 8.0 не использует ту же логику, что и виртуальная таблица в логике наследования классов, а использует механизм приоритета, который выбирает реализацию из ближайшего реализованного интерфейса как единственную доступную реализацию, поэтому проблем с виртуальными таблицами нет.

В интерфейсах по-прежнему нет разрешенных полей, поэтому проблем с полями нет.

Как выбрать между интерфейсом с реализациями по умолчанию и абстрактными классами

  • Синтаксически, если тип должен иметь поля или виртуальные / абстрактные методы с несколькими используемыми переопределениями, из типов в дереве наследования используйте абстрактный класс, в противном случае - интерфейс.

  • По логике вещей, если основная часть логики должна быть реализована в этом типе и некоторые отдельные детали должны быть указаны в производном классе / классе реализации, используйте абстрактный класс. Если тип только указывает, как к нему можно получить доступ, а реализованные методы просто удобны для класса реализации, например, преобразование аргумента из альтернативного типа в в основном реализованный тип, используйте интерфейс с реализациями по умолчанию.

Другие вопросы по тегам