views:

480

answers:

10

For my new Pet-Project I have a question for design, that is decided already, but I want some other opinions on that too.

I have a two classes (simplyfied):

class MyObject
{
  string name {get;set;}
  enum relation {get;set;}
  int value {get;set;}
}

class MyObjectGroup
{
  string name {get;set;}
  enum relation {get;set;}
  int value {get;set;}
  List<MyObject> myobjects {get;set;}
}

Later in the Project MyObjectGroup and MyObject should be used equally. For this I could go two ways:

  • Create an interface: IObject
  • Create an abstract class: ObjectBase

I decided to go the way of the interface, that I later in code must not write ObjectBase everytime but IObject - just for ease - but what are other positives for this way.

And second, what about adding IXmlSerializable to the whole story? Let the interface inherit from IXmlSerializable or does it have more positives to implement IXmlSerializable in abstract base class?

A: 

I've been using abstract classes in my projects, but in future projects, I'll use interfaces. The advantage of "multiple inheritance" is extremely useful. Having the ability to provide a completely new implementation of the class, both in code, or for testing purposes, is always welcome. Lastly, if in the future you'll want to have the ability to customize your code by external developers, you don't have to give them your real code - they can just use the interfaces...

SaguiItay
+7  A: 

Generally speaking, the approach I use in this kind of situation is to have both an interface and an abstract class. The interfaces defines, well, the interface. The abstract class is merely a helper.

You really can't go wrong with this approach. Interfaces give you the flexibility to change implementation. Abstract classes give you boilerplate and helper code that you aren't forced to use, which you otherwise would be if your methods were defined in terms of an abstract class explicitly.

cletus
+2  A: 

Generally, you should consider interfaces as contracts that some types implement and abstract classes as nodes in inheritance hierarchy that don't exist by themselves (i.e. there is an "is a" relationship between the derived class and the base abstract class). However, in practice, you might need to use interfaces in other cases, like when you need multiple inheritance.

For instance, IXmlSerializable is not an "entity" by itself. It defines a contract that an entity can implement. Interfaces live "outside" the inheritance hierarchy.

Mehrdad Afshari
+1  A: 

You could actually go with BOTH. ObjectBase saves you the trouble of implementing the common properties more than once and implements IObject for you. Everywhere you use it refer to IObject so you can do testing with mocks later

n8wrl
+3  A: 

The interface would be my default until there is a reason to use a base class, as it makes fewer decisions for us.

I wouldn't involve IXmlSerializable unless I had to though; it is a messy, tricky interface that is often a cause of woe.

What exactly are your serialization requirements? There may be better options... however, for many serializers a base-class would be easier than an interface. For example, for XmlSerializer you could have:

[XmlInclude(typeof(MyObject))] // : ObjectBase 
[XmlInclude(typeof(MyObjectGroup))] // : ObjectBase 
public abstract class ObjectBase { /*  */ }

(the exact approach depends on the serializer)

Marc Gravell
I agree. You can do XML serialisation without ever touching the interface, and you're much better off for it. If you need some example code for how to get started with XML serialisation sans IXmlSerializable, have a look at this question, it has some (albeit, limited) examples on how to invoke the serialiser: http://stackoverflow.com/questions/1115459/xml-deserialization-standardising-line-endings-how-to-stop-it-net , and then look up the `Xml*` attributes
Matthew Scharley
That does not work if you have collecions as properties, sub-elements are not automatically serialized while serializing the object. Although I do not have tested this on mono, what I do use now.
BeowulfOF
Yes they are... simply that (annoyingly) any list (etc) needs to have public get/set and a concrete container type with a parameterless constructor - i.e. `public List<Customer> Customers {get;set;}`. You can get around this using DataContractSerializer, or protobuf-net, etc - neither of which requires this.
Marc Gravell
+1  A: 

An Interface will allow you to define a 'contract' that the object will need to fulfil by delivering properties and methods as described by the interface. You can refer to objects by variables of interface-type which can cause some confusion as to what exactly is being offered.

A base class offers the opportunity to build an inheritance 'tree' where more complex classes (of a common 'type') are built on the foundations of a simpler 'base' classes. The classic and annoying example in OO is normally a base class of 'Shape' and which is inherited by Triangle, Square, etc.

The main point is that with an Interface you need to provide the entire contract with every class that implements it, with an inheritance tree (base classes) you are only changing/adding the properties and methods that are unique to the child class, common properties and methods remain in the base class.

In your example above I'd have the 'MyObjectGroup' object inherit the base 'MyObject' class, nothing to be gained from an interface here that I can see.

Lazarus
A: 

I'd rather go for base abstract class, because, theoretically (well, it's just one theory, I'm not proving or saying that any other is worse then this) - interfaces should be used, when you want to show, that some object is capable of doing something (like IComparable - you show that whatever implements it, can be compared to something else), whereas when you have 2 instances that just share something common or have 1 logical parent - abstract classes should be used.
You could also go for both approaches, using base class, that will implement an interface, that will explicitly point what your class can do.

Ravadre
A: 

If you have function in class,you should use abstact class instead of interface. In general,an interface is used to be on behalf of a type.

Edwin Tai
A: 

Note that you cannot override operators in Interfaces. That is the only real problem with them as far as I'm concerned.

David Rutten
A: 

All else being equal, go with the interface. Easier to mock out for unit testing.

But generally, all I use base classes for is when there's some common code that I'd rather put in one place, rather than each instance of the derived class. If it's for something like what you're describing, where the way they're used is the same, but their underlying mechanics are different, an interface sounds more appropriate.

Sterno