views:

397

answers:

6

So, hypothetically, I'm building some sort of real estate application in C#. For each type of property, I'm going to create a class such as ResidentialProperty and CommercialProperty. These two classes as well as all other property classes will share some common properties, such as Id, Title, Description, and Address information.

What I would like to be able to do is:
a) return a collection of objects that contain just the basic information
b) be able to either call a method such as GetProperty(id) which will create and return either a ResidentialProperty or CommercialProperty, or call GetProperties() which will return a collection of one or the other, or both.

So with that said, it would probably make sense to create an abstract class called BasicProperty (or PropertyBase) which contains all of the common attributes, and have the ResidentialProperty and CommercialProperty extend from it. This would take care of problem #1, as I could create a method that returns a collection of BasicProperties.

But for #2, being able to return either one property type or the other, I would need an Interface (IProperty), and have the Residential and Commercial classes inherit from it, and then have the GetProperty(id) and GetProperties() return an IProperty object (or because they inherit from IProperty, can I return them as is and not as the Interface?)?

Now if I should use an Interface, what do I do with the BasicProperty class?
- Do I leave it as an abstract and implement the Interface? Or
- Do I leave it as an abstract and all 3 classes implement the Interface? Or
- Do I not create it as an abstract, put all of the basic information into the Interface, and the BasicProperty, ResidentialProperty and CommercialProperty all implement the Interface?

Thanks in advance, Carl J.

A: 

From what I can gather, you are talking about two different things here.

  1. Class structure
  2. Data Access of those classes

You are correct in thinking that you should create an abstract class to contain the common properties, that's what inheritance is for :) (among other things)

But I dont see why you can't create a data access class that has a method GetProperty(id) that specifies a return type of PropertyBase

i.e.

public PropertyBase GetProperty(long id)

in the implementation of GetProperty you can construct a ResidentialProperty or CommercialProperty (based on what ever business/database logic you want) then return it, c# allows you to do that.

Perhaps I miss-understood you?

HTH

EDIT::

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
        }
    }

    class DataAccessLayer
    {
        public PropertyBase GetSomething(int id)
        {
            if (id > 10)
                return new CommercialProperty();
            else
                return new ResidentialProperty();
        }

    }

    class PropertyBase { }
    class ResidentialProperty : PropertyBase { } 
    class CommercialProperty : PropertyBase { }
}
Mark
So, if I say that the return type of a method is PropertyBase (the abstract class), I can then return either a Residential or Comemercial object? I thought that for a method to be able to return different types, that each type had to implement an Interface.
Carl J
yep, see my example that I added
Mark
Yes, you can return the base class and treat both Residental and Commercial as a common set of base objects. This is what's known in OOP parlance as LSP, or Liskov Substitution Principle, and basically it means that if you inherit from something, then it can be treated as both the concrete subclass and the (possibly abstract) base class. Inheritence is an "IS A" relationsip. A ResidentialProperty *IS A* PropertyBase. A CommercialProperty *IS A* PropertyBase also.
Mystere Man
Carl's "residence" class adds fields #Bathrooms, #Bedrooms (see Carl's comment on Adam's answer). When multiple classes inherit from an abstract class : each inheriting class can implement or omit fields, methods of the abstract class, etc. : and add additional "whatever" to its implementation : any time you return a derived class object "down cast" to its abstract base class type : you will then "hide" anything added by the derived class. Don't be surprised if #Bedrooms, #Bathrooms variables "disappear" when you return "residence" as a base-type.
BillW
A: 

An abstract class is used to provide common behaviour. An interface is used to provide a specific set of methods and properties, regardless of how they behave.

If your ResidentialProperty and CommercialProperty provide some common behaviour then it probably makes sense to implement this behaviour in an abstract class and have each of them inherit from this class. Presumably they also will have some custom behaviour ,otherwise there is no need to sub-class, it would then be sufficient just to have a PropertyType property to describe which type of Property the instance is.

You can then provide as many interfaces as you feel would be useful, IPropertyBase, IResidentialProperty and/or ICommercialProperty. It really depends on whether you expect this library to be used a base for other implementations which may have the same interface as one or more of your classes, but not the same behaviour as your base abstract class. The other benefit of exposing interfaces which represent your types is easier mocking for unit testing.

It's not really possible to answer this question absolutely because it really depends on how your objects are likely to be used, but I hope this answer provides you with a useful guideline.

AdamRalph
Thanks Adam. Both the Residential and Commercial classes share common attributes (Id, Title, Description, Address), however they each have their own seperate attributes. Residential would have NumberOfBedroom and NumberOfBathrooms, while Commercial would have others that Residential doesn't have.
Carl J
I'm unsure if you intend this to be a complex system or not, if so then I wouldn't rule out any given attribute for any given property type. Certainly commercial properties can have bedrooms and bathrooms, and residential properties can have office space. You might, insteand, consider a unified property object that has a custom definable set of attributes that can be applied uniquely to each property, perhaps providing common templates of properties to use for residential and comemrcial properties, but not requiring them.
Mystere Man
A: 

It is my opinion that you should avoid using abstract classes unless it absolutely makes sense you should.

A lot of the common behaviour can be given to your entities through aggregation, using components and you can publicise this behaviour through the use of interfaces.

The reason I tend to go down this route, is that once you have an abstract base class, you're tied to using it, as you can't have multiple inheritance.

Sooner or later, you end up with a situation in which you DO want multiple inheritance and you're screwed.

Not that I'm a hardliner on this, because plenty of our code-base does utilise base abstract classes for the above, but those implement the interfaces and all the code enacting on those classes talk to them through the interfaces, so we can switch out the base classes for something more flexible later if necessary.

Rob Ashton
There's some great info in the book "Framework design guidelines" about when to use interfaces and when to use abstract classes.
Si
I sincerely wish I could read a robust article outlining the implementation strategy you describe above with code exampes :)
BillW
A: 

A quick not about the difference as I see it. You can always use an abstract base class even when you implement interfaces. Interfaces does not help you avoid code duplication which you should (see the DRY principle) but it doesn't force you to derive from anything special which makes them easier to combine with other base classes or interfaces.

An abstract base class on the other hand can remove some duplication and it is easier to change some things in the base without touching the derived classes. The latter is very nice when you implement a class library that others use. If you change things in interfaces in a library, all implementations of that interface needs to change! This might be a very small problem if you only implement an application with a small group of developers. But as other has said, a base class forces you to derive from it and then you cannot derive from something else if that need should appear.

Johan Bergens
A: 

Don't call your base class or interface BasicProperty or PropertyBase, just call it Property. You will not have both a Property and a BasicProperty, will you? You will act with Property classes or interfaces.

An abstract class is almost the same as an interface with the difference that the abstract class can store state in field variables. When your Properties have data like the address that is stored an abstract class with a field is one way to do that.

Now the subclassing of a class is one of the picture book examples of OOD, but there are other ways of differentiating objects than that, look at the decorator and behavior patterns. You should subclass only if you need to override methods of the base class. Have a look at this for example.

Ozan
Another difference between interfaces and abstract classes is that a class can implement behavior, an interface cannot, it only defines the contract syntax. Also, inheritance (subclassing) can be used to extend a class, adding new properties and methods, as well as, but not limited to, overriding virtual methods.
Si
A: 

While I feel that defining an interface to begin with is almost always a good idea, just because it helps your code to be flexible in the future, it sounds like in this case you don't actually need to do that. Your GetProperty and GetProperties methods can use your abstract base class as a return value.

Think of it like this: What if I had a method called GetShape? It would presumably return a Shape, right? Let's say Shape is an abstract base class, and some derived classes are Triangle, Square, Circle, etc.

But a triangle is a shape, a square is a shape, and so on--each of these happens to be more than just a shape, but they are shapes nonetheless. So if I say "give me a shape" and you hand me a square, you're doing just as I asked. No funny business there.

This is one of the core underlying principles of OOP: an instance of a derived class is an instance of its base class; it's just also more than that.

Dan Tao