Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inherit members from multiple class

Tags:

c#

oop

I've been learning to design with OOD and stuck with a scenario.

I have a class User which extends an abstract class Person. Class Person has a member with type Address. User only have Username and Password, and Address have some string fields.

Now, I want to add a class Client which can be a Person or an Organization(to be added). Client will have some data also.

I thought about interfaces but they can have only methods. Can anyone help me with what will be the proper design?

I'm not following any pattern and coding with C#.NET.


Update

I think I could not explain the scenario properly. Sorry for that. Please, have a look on the diagram. Here, the Client class is what I want to add. Incomplete class diagram of my scenario

like image 363
Raihan Avatar asked Oct 03 '22 03:10

Raihan


1 Answers

Try to work with composition. A person and an organization are not necessarily a user, although they both can HAVE an address or a user account. Actually they most likely have more than one of both.
If you think more in terms of HAS A and less in terms of IS A you can come up with more maintainable choices. For instance you can have a

class Address {
  public string street {get; private set;}
  public string city {get; private set;}
  public AddressTypes AddressType {get; private set;} // an enum to differentiate 
                                                      // "home address", "legal address"
  ...
}

now, if you need to model the fact that both a Person and a Organization are things that must have Addresses, you can create an interface

interface IAddressable {
   IEnumerable<Address> {get;}
}

and have both Person and Organization implement it. The same can be done with an Account class that holds Username and Password.

Now Person and Organization don't need to BE Users, but they can both HAVE Accounts, Addresses and anything else you need. And you can force them to have these things via interfaces, as shown above.

As for Client, I can see your problem. You are tempted to say that "a Person (or an Organization) IS a Client". But in your design "a Person IS already a User" and you can't have Person inherit from two different base classes.

However, note that a Person is not necessarily a client. I'm not sure what a Client exactly is in your model, but let's assume it's someone with an Address and an Account who can be a Person or an Organization (and you want to know if it's one or the other). You can do this in several ways, but one could be:

abstract class Client : IAddressable, IWithAccount {
   // implement IAddressable and IWithAccount
}

class PersonClient : Client
{
    public PersonClient(Person person)
    {
        // make the Client's address refer to the Person's address
        // make the Client's account refer to the Person's account
    }
}

class OrganizationClient : Client
{
    public OrganizationClient(Organization organization)
    {
        // make the Client's address refer to the Organization's address
        // make the Client's account refer to the Organization's account
    }
}

the advantages are that:

  • you don't have to change your existing code to retro-fit a role (Client) as a base class of existing entities (Person, Organization).
  • if your company starts having for instance States as Clients, you can add a StateClient without changing the existing pieces
like image 93
Paolo Falabella Avatar answered Oct 13 '22 11:10

Paolo Falabella