C# 7.0 - добиться множественного наследования с реализацией по умолчанию - PullRequest
1 голос
/ 20 марта 2020

Вопрос: как обеспечить как множественное наследование (не разрешено C#), так и реализацию методов по умолчанию (не разрешено интерфейсом в C# <8.0)? </p>

Общий сценарий - когда у меня есть первый уровень абстракции, затем второй уровень абстракции, генерирующий два разных семейства / категории, и, наконец, конкретная реализация чего-то, что принадлежит обоим вышеуказанным семействам / категориям.

Пример кода, который я написал, следующий (но, пожалуйста, не зацикливайтесь на деталях реализации, просто рассмотрите это как описательный сценарий):

public abstract class Message
{
    protected Guid _id;
    protected string _body;
    protected Message(string body)
    {
        _body = body;
    }
    public override string ToString()
    {
        return _id + "|" + _body;
    }
}
public abstract class ReceivableMessage : Message
{
    private string _receivedFrom;
    public ReceivableMessage(string body, string receivedFrom)
    : base(body)
    {
        _receivedFrom = receivedFrom;
    }
    public string GenerateReply()
    {
        //do some generation
        return "";
    }
}
public abstract class SendableMessage : Message
{
    private string _sendTo;
    public SendableMessage(string body, string sendTo)
    : base(body)
    {
        _sendTo = sendTo;
    }
    public bool CheckReply(ReceivableMessage reply)
    {
        //do some check
        return true;
    }
}

тогда у меня есть несколько конкретных реализации как ReceivableMessage, так и SendableMessage; но теперь я хочу добавить конкретные классы AckMessage и NackMessage ... они должны расширять как ReceivableMessage, так и SendableMessage (потому что оба могут быть получены и отправлены) ... как я могу этого достичь?
В качестве дополнительных комментариев я рассмотрел две возможности, но отбросил их:

  1. заменил 3 абстрактных класса на 3 интерфейса. Не хорошо, потому что я потерял бы общие реализации методов ToString, GenerateReply и CheckReply, и я должен повторить их во всех конкретных классах, а также в общих полях _id, _body, _receivedFrom и _sendTo (даже если технически этого можно избежать, заменив их свойствами).
  2. предоставляет конкретные реализации для AckReceivableMessage и NackReceivableMessage (унаследованные от ReceivableMessage), а также AckSendableMessage и NackSendableMessage (наследование от SendableMessage). Не в порядке, мне кажется, это дублирование кода.

1 Ответ

1 голос
/ 20 марта 2020

Я создал множественное наследование с помощью динамической отправки c. Это слишком сложный способ реализации sh свойств системы массовой настройки. В сущности, вам нужна возможность интегрировать обработку из нескольких модулей. Производственная архитектура позволяет контейнеру бесконечно расти - эти термины взяты из бизнеса - двумя способами:

  • Вертикально: расширение процесса (вместо создания подклассов)
  • Горизонтально : добавление новых процессов (вместо того, чтобы создавать подклассы или наследовать для этого)

Другая проблема множественного наследования состоит в том, что он вносит неоднозначность. Неясно, какой метод должен вызываться при наследовании обоих классов.

    class A
    {
        public void One() { ... }
    }
    class B
    {
        public void One() { ... }
    }

Производственная архитектура, такая как массовая настройка, однако моделирует процессы как целые классы, а не просто методы, и поэтому вышеупомянутая проблема предотвращается пространствами имен .

namespace A
{
    class OneProduct { ... }
    class One : Producer<OneProduct>, IProcess { ... }
}

namespace B
{
    class OneProduct { ... }
    class One : Producer<OneProduct>, IProcess { ... }
}

// example of a hardcoded process
namespace IntegratingProcess
{
    class MyProduct { ... }
    class MyProcess : Producer<OneProduct>, IProcess 
    {
        private A.One Machine1 { get; set; }
        private B.One Machine2 { get; set; }
        void D() { // allocate memory for all machines and product DTO }
        void O() { // binds Machine1 and Machine2 to MyProduct reference properties }
        void M()
        {
            Machine1.M();
            Machine2.M();
        }
    }

}

Массовая настройка позволяет динамически интегрировать обработку и изменять порядок запуска. Это, конечно, альтернатива жестко закодированной форме, описанной выше, где производственный процесс и порядок его запуска строятся во время компиляции. Моя статья на R посвящена массовой настройке, но я не даю исходный код для нее.

Я являюсь разработчиком POWER, производственной архитектуры и правил для ее эффективного использования. Мои статьи учат программистов, как правильно моделировать совместную работу с исходным кодом.

http://www.powersemantics.com/power.html

...