-4

Let’s say there are 2 classes that have the same prop, with logic in that prop as well.

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

And

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

Ideally, you’d make an abstract base class (BaseSSN) these would inherit from. That’s all well and good, but not ideal! The reason for this is because in C# you can only inherit from 1 super class. That means that if you have a case where Manager and Employee both have SSN, but Manager and a new class (CEO) have a ManagerOf property, then you have to then create a new class that implements the BaseSSN class but it would also be an abstract class (BaseManagerOf) that has the logic for Managerof inside of it. Then, Manager and CEO would inherit from the new class. However, now you would have to create still another class if someone was a manager but themselves did not have an SSN. You would need to pull out the Manager prop and put it in a super, to separate it from the SSN class.

Do you see where I’m going with this? It could create N number of variations depending on the amount of props each class has that are similar to other classes.

So what I would like to do is simply

Public class Manager : BaseSSN, BaseManagerOf, X

Where X is anything. You can do this with interfaces, but interfaces can’t contain logic.

I believe there is probably a smooth strategy that will solve this, but can’t figure it out for the life of me.

EDIT:

There seems to be a small amount of confusion regarding my question: this is a hypothetical question. I understand that managers are employees. The simple question is that i want one class to implement 2 abstracts and cannot do that in C#. However, is there a strategy that would allow this to work in any way?

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 {}

Now it begins to fall apart with CEO. I don't want the CEO's SSN, only the person he manages. So I would have to pull the logic out of the ManagerOf class that inherits SSN, and put that in its own class. Then CEO wouldn't have the SSN prop. However, now I can't have both ManagerOf logic and SSN logic in my Manager class without creating yet another abstract that looks like the following class...

public class ManagerOfAndSSN: SSN
{
    // repetitive manager logic here
}
  • Why would you split out the SSN only and inherit from that? That doesn't really make sense... An employee is not an SSN... – Broots Waymb Feb 13 '19 at 17:38
  • 1
    What happens if someone sets that SSN property to a null or to the empty string (`thing.SSN = someAccidentallyEmptyString;`). Quietly ignoring an action like that is a great way to have an intermittent problem no one will ever be able to track down. One solution (to your question) is to make SSN a class on it's own (capable of interpreting multiple input formats (other than just a Regex matching `@"\d{9}"`, able of formatting itself several ways (including "last 4"). Then you let it do your setter logic – Flydog57 Feb 13 '19 at 17:39
  • 2
    Why is Manager not a kind of Employee? Every manager I know is also an employee. – Eric Lippert Feb 13 '19 at 17:42
  • Apparently "interfaces that have a default implementation" is proposed as a feature for C# 8, which would solve your problem. Java already has this feature, and it is quite useful. – Eric Lippert Feb 13 '19 at 17:43
  • Does "hypothetical question" mean you don't actually want an answer? – matt-dot-net Feb 13 '19 at 18:38
  • No, that is a "rhetorical question". I definitely wouldn't have asked it if I didn't want an answer. – Tyler Youngs Feb 13 '19 at 19:14
  • Ok good. Hypothetically, If C# supported multiple inheritance you could use multiple inheritance. – matt-dot-net Feb 13 '19 at 19:20
  • Possible duplicate of [Multiple Inheritance in C#](https://stackoverflow.com/questions/178333/multiple-inheritance-in-c-sharp) – matt-dot-net Feb 13 '19 at 19:22

1 Answers1

0

One answer is to use interfaces and composition. Your "base" classes that implement the functionality (e.g. ManagerOf or SSN) implement the interface, and then you provide those as dependencies to classes that need them:

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

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

Now you can inject those classes in the classes that compose them together:

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

Or, an alternative implementation of the classes:

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

This is a fairly trivial implementation, and in this case I'd opt to simply implement the interfaces in each class supporting the functionality. If, however, you had more complex logic around the properties, the composition route makes more sense since you are sharing the implementation then. It's not as "elegant" as multiple inheritance seems at first, but see Why is Multiple Inheritance not allowed in Java or C#? for some discussion of why multiple inheritance is often thought to cause more trouble than it solves.

Colin Young
  • 3,018
  • 1
  • 22
  • 46