C#中的多重继承替换-属性中带有逻辑的特定假设示例

C#中的多重继承替换-属性中带有逻辑的特定假设示例,c#,object,inheritance,interface,abstract,C#,Object,Inheritance,Interface,Abstract,假设有两个类具有相同的属性,该属性中也包含逻辑 public class Manager { private string _ssn { get; set; } [RegularExpression(@"\d{9}")] public string SSN { get { return _ssn; } set { if (!string

假设有两个类具有相同的属性,该属性中也包含逻辑

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);
        }     
    }
}

理想情况下,您应该创建一个抽象基类(BaseSSN),这些基类将从中继承。这一切都很好,但并不理想!这是因为在C#中,只能从一个超类继承。这意味着,如果经理和员工都有SSN,但经理和新类(CEO)有ManagerRof属性,那么您必须创建一个实现BaseSSN类的新类,但它也是一个抽象类(BaseManagerRof),其中包含ManagerRof的逻辑。然后,经理和首席执行官将继承新类别。但是,如果有人是经理,但他们自己没有SSN,那么现在还必须创建另一个类。您需要拉出Manager道具并将其放入super中,以将其与SSN类分离

你知道我要说什么吗?它可以根据每个职业拥有的与其他职业相似的道具数量,创建N个变化

所以我想做的只是

公共类管理器:BaseSSN、BaseManagerOf、X

其中X是任何东西。您可以通过接口实现这一点,但接口不能包含逻辑

我相信可能会有一个平稳的策略来解决这个问题,但我一辈子都想不出来

编辑:

关于我的问题,似乎有一些困惑:这是一个假设性的问题。我知道经理是员工。简单的问题是,我想要一个类来实现两个抽象,但在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 {}
现在,它开始与首席执行官分道扬镳。我不想要CEO的SSN,只想要他管理的人。因此,我必须从继承SSN的ManagerRof类中提取逻辑,并将其放入自己的类中。那么CEO就不会有SSN的支持了。然而,现在我不能在我的Manager类中同时包含ManagerRof逻辑和SSN逻辑,而不创建另一个类似于以下类的抽象

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

一个答案是使用接口和组合。实现功能的“基类”(例如,
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 { ... }

这是一个相当简单的实现,在本例中,我选择简单地实现支持该功能的每个类中的接口。但是,如果您在属性周围有更复杂的逻辑,那么组合路由就更有意义,因为您当时正在共享实现。它一开始并不像多重继承看起来那么“优雅”,但有关为什么多重继承通常被认为会带来比它解决的问题更多的麻烦的一些讨论,请参见。

为什么您只拆分SSN并从中继承?这真的没有道理。。。员工不是SSN…如果有人将SSN属性设置为null或空字符串(
thing.SSN=someAccidentallyEmptyString;
),会发生什么情况。悄悄地忽略这样的行为是一种很好的方法,可以让人发现一个没有人能够追踪到的间歇性问题。(针对您的问题)的一个解决方案是使SSN本身成为一个类(能够解释多种输入格式(而不仅仅是与
@“\d{9}”
匹配的正则表达式),能够以多种方式格式化自身(包括“last 4”)。然后你让它做你的setter逻辑。为什么经理不是一种员工?我认识的每一位经理都是员工。显然,“具有默认实现的接口”是C#8的一项功能,这将解决你的问题。Java已经有了这项功能,而且它非常有用。“假设问题”是吗你是说你不想得到答案?
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;
}