简体   繁体   中英

Aggregation versus Inheritence in C#, or alternatives

Let's say I have the following two classes:

public class Person
{
    public string Name { get; set; }
    public string Address { get; set; }
}
public class Customer: Person
{
    public string CustomerNumber { get; set; }
    public string PaymentTerms { get; set; }
}

Now, if I have a person that I want to make a customer, I have, to the best of my knowledge, three options, and I'm hoping for advice on which is the best and on any other options, maybe using the new dynamics stuff in C#4.

I can add a constructor or property to Customer that takes a Person and assigns values to the base class, eg

public Customer(Person person)
{
    base.Name = person.Name;
    base.Address = person.Address;
}

or I can implement an untidy set accessor like this:

public Person Person
{
    set
    {
        Name = value.Name;
        Address = value.Address;
    }
}

or I can aggregate Person into Customer like this:

public class Customer
{
    public Person Person { get; set; }
    public string CustomerNumber { get; set; }
    public string PaymentTerms { get; set; }
}

The last is to me the neatest, except for always having to eg access Customer.Person.Name , instead of just Customer.Name .

I would personally go for composition, yes (your last option). Note that you can always provide "helper properties":

public string Name { get { return Person.Name; } }

Indeed, you can do this for all the properties you want, and never expose the Person property to the outside world at all.

On the other hand, inheritance is useful if you want to be able to treat a Customer as a Person - passing it to methods with a Person parameter, for example. I usually accomplish that sort of thing with interfaces though; you could have an IPerson interface implemented by both Customer and Person . Inheritance introduces all sorts of design decisions which simply don't come up (or are a lot simpler) when you don't get into inheritance.

I'd either use the constructor, or maybe a factory method, like

public static Customer CreateFromPerson(Person person)
{
    return new Customer(){ Name = person.Name }//etc...
}

I don't like the setter as you're not actually setting the 'Person' on a customer, and I don't like the last option because it leads to a Law of Demeter (LOD) violation when you access the person through the customer (customer.person.name etc).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM