tags:

views:

71

answers:

2

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, e.g.

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 e.g. access Customer.Person.Name, instead of just Customer.Name.

+4  A: 

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.

Jon Skeet
Customer is also a person (inherited from Person). So clean implementation requires Person's properties to be virtual so that they can be overridden in Customer to return values from child person object.
VinayC
I'd be interested in your rationale, as I've always tended to stick to the first option (albeit with calling a base constructor, rather than setting properties that may change over time)
Rowland Shaw
ProfK
@VinayC: That depends whether Person is designed to be specialized in that sort of way. Maybe it's not. You shouldn't make *everything* in a base class virtual, generally. This is the sort of thing which makes inheritance tricky to design. It also restricts the ability for the implementation to change, and requires more detailed documentation.
Jon Skeet
@Jon: I completely agree. My comment was just a reflection on the fact that ProfK had already chosen to inherit Customer from Person that would actually force him to have virtual properties if he has to use composite person. As such, my guess is that 9 out of 10 software developers would have inherited Customer from Person.
VinayC
@VinayC: I certainly wouldn't mix inheritance *and* composition, but I don't think ProfK was suggesting that. He hasn't really already chosen inheritance - that's just one of the options he's considering. (See the last bit of his question for an alternative which doesn't use inheritance.)
Jon Skeet
+3  A: 

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).

Grant Crofton
+1 for broadening my understanding of LOD. I thought it was much narrower, being only fields should not be directly accessed from outside etc.
ProfK