简体   繁体   中英

C# - What should I use, an Interface, Abstract class, or Both?

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.

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.

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

ie

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

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.

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.

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.

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.

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