Заменитель множественного наследования в C # - конкретный гипотетический пример с логикой в ​​свойствах - PullRequest
0 голосов
/ 13 февраля 2019

Допустим, есть 2 класса, которые имеют одинаковую опору, с логикой в ​​этой опоре.

public class Manager
{
    private string _ssn { get; set; }

    [RegularExpression(@"\d{9}")]
    public string SSN
    {
        get
        {
            return _ssn;
        }
        set
        {
            if (!string.IsNullOrEmpty(value))
                _ssn = someLogicalMethod (value);
        }     
    }
}

И

public class Employee
{
    private string _ssn { get; set; }

    [RegularExpression(@"\d{9}")]
    public string SSN
    {
        get
        {
            return _ssn;
        }
        set
        {
            if (!string.IsNullOrEmpty(value))
                _ssn = someLogicalMethod(value);
        }     
    }
}

В идеале вы должны сделать резюмебазовый класс (BaseSSN), от которого они наследуются.Это все хорошо, но не идеально!Причина этого в том, что в C # вы можете наследовать только от 1 суперкласса.Это означает, что если у вас есть случай, когда Manager и Employee оба имеют SSN, а Manager и новый класс (CEO) имеют свойство ManagerOf, то вам необходимо создать новый класс, который реализует класс BaseSSN, но он также будетабстрактный класс (BaseManagerOf), в котором есть логика для Managerof.Тогда менеджер и генеральный директор унаследуют от нового класса.Однако теперь вам придется создавать еще один класс, если кто-то был менеджером, но у них не было SSN.Вам нужно было бы достать реквизит Manager и поместить его в супер, чтобы отделить его от класса SSN.

Вы понимаете, куда я иду с этим?Он может создать N вариантов в зависимости от количества реквизитов каждого класса, которые похожи на другие классы.

Итак, я бы хотел просто

Public class Manager: BaseSSN,BaseManagerOf, X

Где X это что-нибудь.Вы можете сделать это с интерфейсами, но интерфейсы не могут содержать логику.

Я полагаю, что, вероятно, есть плавная стратегия, которая решит эту проблему, но не могу понять это для моей жизни.

РЕДАКТИРОВАТЬ:

Кажется, естьнебольшая путаница в отношении моего вопроса: это гипотетический вопрос.Я понимаю, что менеджеры являются сотрудниками.Простой вопрос заключается в том, что я хочу, чтобы один класс реализовал 2 реферата, и не могу этого сделать в C #Однако существует ли стратегия, которая позволила бы этому работать каким-либо образом?

public class Manager : BaseManager
{
}

public abstract class BaseManager : BaseSSN
{

    private string _managerOf;
    public int ManagerOf
    { 
         get
         {
             return _managerOf;
         }
         set
         {
             if (!string.IsNullOrEmpty(value))
                 _managerOf = someLogicalMethod(value);
         }     
     }
}

public abstract class BaseSSN
{
    private string _ssn { get; set; }

    [RegularExpression(@"\d{9}")]
    public string SSN
    {
        get
        {
            return _ssn;
        }
        set
        {
            if (!string.IsNullOrEmpty(value))
                _ssn = someLogicalMethod(value);
        }     
    }
}

public class CEO : ManagerOf {}

Теперь он начинает разваливаться вместе с генеральным директором.Я не хочу SSN генерального директора, только человека, которым он управляет.Поэтому мне придется извлечь логику из класса ManagerOf, который наследует SSN, и поместить его в свой собственный класс.Тогда у генерального директора не будет поддержки SSN.Однако теперь у меня не может быть логики ManagerOf и логики SSN в моем классе Manager, если я не создал еще один реферат, похожий на следующий класс ...

public class ManagerOfAndSSN: SSN
{
    // repetitive manager logic here
}

1 Ответ

0 голосов
/ 13 февраля 2019

Один ответ - использовать интерфейсы и композицию.Ваши «базовые» классы, которые реализуют функциональность (например, ManagerOf или SSN), реализуют интерфейс, а затем вы предоставляете их в качестве зависимостей для классов, которые в них нуждаются:

public interface ISsn
{
    string Ssn { get; set; }
}
public interface IManagerOf
{
    List<Employee> Manages { get; set; }
}

public class Ssn : ISsn { ... }
public class ManagerOf : IManagerOf { ... }

Теперь вы можете внедрить теклассы в классах, которые составляют их вместе:

// here we are implementing the interfaces on the class
public class Employee : ISsn
{
    private ISsn _ssn;

    public Employee(ISsn ssn)
    {
        _ssn = ssn;
    }

    public string Ssn
    {
        get { return _ssn.Ssn; }
        set { _ssn.Ssn = value }
    }
}

public class Manager : ISsn, IManagerOf
{
    private ISsn _ssn;
    private IManagerOf _managerOf;

    public Employee(ISsn ssn, IManagerOf managerOf)
    {
        _ssn = ssn;
        _managerOf = managerOf;
    }

    public string Ssn
    {
        get { return _ssn.Ssn; }
        set { _ssn.Ssn = value }
    }

    public List<Employee> Manages
    {
        get { return _managerOf.Manages; }
        set { _managerOf.Manages = value; }
    }
}

Или, альтернативная реализация классов:

// here we're just going to expose each dependency as the interface
public class Employee : ISsn
{
    private ISsn _ssn;

    public Employee(ISsn ssn)
    {
        _ssn = ssn;
    }

    public ISsn Ssn => _ssn;
}

public class Manager2
{
    private ISsn _ssn;
    private IManagerOf _managerOf;

    public Employee(ISsn ssn, IManagerOf managerOf)
    {
        _ssn = ssn;
        _managerOf = managerOf;
    }

    public ISsn Ssn => _ssn;
    public IManagerOf ManagerOf => _managerOf;
}

Это довольно тривиальная реализация, и в этом случае я бывыберите просто реализовать интерфейсы в каждом классе, поддерживающие функциональность.Однако, если у вас была более сложная логика вокруг свойств, составной маршрут имеет больше смысла, так как тогда вы делитесь реализацией.Это не так «элегантно», как поначалу кажется множественное наследование, но см. Почему множественное наследование не разрешено в Java или C #? , чтобы обсудить, почему множественное наследование часто вызывает больше проблем, чем решает.

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