简体   繁体   中英

Interface or abstract class?

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 two classes (simplified):

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 every time 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?

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.

These are some of the differences between Interfaces and Abstract classes.

1A. A class may inherit (Implement) one or more interfaces. So in C#, interfaces are used to achieve multiple inheritance.
1B. A class may inherit only one abstract class.

2A. An interface cannot provide any code, just the signature.
2B. An abstract class can provide complete, default code and/or just the details that have to be overridden.

3A. An interface cannot have access modifiers for the subs, functions, properties etc everything is assumed as public.
3B. An abstract class can contain access modifiers for the subs, functions, properties.

4A. Interfaces are used to define the peripheral abilities of a class. For eg. A Ship and a Car can implement a IMovable interface.
4B. An abstract class defines the core identity of a class and there it is used for objects.

5A. If various implementations only share method signatures then it is better to use Interfaces.
5B. If various implementations are of the same kind and use common behaviour or status then abstract class is better to use.

6A. If we add a new method to an Interface then we have to track down all the implementations of the interface and define implementation for the new method.
6B. If we add a new method to an abstract class then we have the option of providing default implementation and therefore all the existing code might work properly.

7A. An interface can not have fields defined.
7B. An abstract class can have fields and constants defined.

8A. An interface can not have constructor.
8B. An abstract class can have default constructors implemented.

9A. An interface can only inherit from other interfaces.
9B. An abstract class can inherit from interfaces, abstract class, or even class.

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)

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 (ie 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.

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.

There are two thing is in Architect's mind when designing classes.

  1. Behavior of an object.
  2. object's implementation.

If an entity has more than one implementation, then separating the behavior of an object from its implementation is one of the key for maintainability and decoupling. Separation can be achieved by either Abstract class or Interface but which one is the best? Lets take an example to check this.

Lets take a development scenario where things (request, class model, etc) are changing very frequently and you have to deliver certain versions of application.

Initial problem statement : you have to create a “Train” class for Indian railway which has behavior of maxSpeed in 1970 .

1. Business Modeling with abstract class

V 0.0 (Initial problem) Initial problem statement : you have to create a Train class for Indian railway which has behavior of maxSpeed in 1970 .

public abstract class Train {
    public int maxSpeed();
}

V 1.0 (Changed problem 1) changed problem statement : You have to create a Diesel Train class for Indian railway which has behavior of maxSpeed, in 1975.

public abstract class DieselTrain extends train {
     public int maxFuelCapacity ();
}

V 2.0 (Changed problem 2) chanded problem statement : you have to create a ElectricalTrain class for Indian railway which has behavior of maxSpeed , maxVoltage in 1980.

public abstract class ElectricalTrain extends train {
     public int maxvoltage ();
}

V 3.0 (Changed problem 3 )

chanded problem statement : you have to create a HybridTrain (uses both diesel and electrcity) class for Indian railway which has behavior of maxSpeed , maxVoltage,maxVoltage in 1985 .

public abstract class HybridTrain extends ElectricalTrain , DisealTrain {
    { Not possible in java }
}
{here Business modeling with abstract class fails}

2. Business Modeling with interface

Just change abstract word to interface and …… your Business Modeling with interface will succeeds.

http://javaqna.wordpress.com/2008/08/24/why-the-use-on-interfaces-instead-of-abstract-classes-is-encouraged-in-java-programming/

Interface: If your child classes should all implement a certain group of methods/functionalities but each of the child classes is free to provide its own implementation then use interfaces.

For eg if you are implementing a class hierarchy for vehicles implement an interface called Vehicle which has properties like Colour MaxSpeed etc. and methods like Drive(). All child classes like Car Scooter AirPlane SolarCar etc. should derive from this base interface but provide a seperate implementation of the methods and properties exposed by Vehicle.

–> If you want your child classes to implement multiple unrelated functionalities in short multiple inheritance use interfaces.

For eg if you are implementing a class called SpaceShip that has to have functionalities from a Vehicle as well as that from a UFO then make both Vehicle and UFO as interfaces and then create a class SpaceShip that implements both Vehicle and UFO .

Abstract Classes:

–> When you have a requirement where your base class should provide default implementation of certain methods whereas other methods should be open to being overridden by child classes use abstract classes.

For eg again take the example of the Vehicle class above. If we want all classes deriving from Vehicle to implement the Drive() method in a fixed way whereas the other methods can be overridden by child classes. In such a scenario we implement the Vehicle class as an abstract class with an implementation of Drive while leave the other methods / properties as abstract so they could be overridden by child classes.

–> The purpose of an abstract class is to provide a common definition of a base class that multiple derived classes can share.

For example a class library may define an abstract class that is used as a parameter to many of its functions and require programmers using that library to provide their own implementation of the class by creating a derived class.

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

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.

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.

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

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.

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

Choosing interfaces and abstract classes is not an either/or proposition. If you need to change your design, make it an interface. However, you may have abstract classes that provide some default behavior. Abstract classes are excellent candidates inside of application frameworks.

Abstract classes let you define some behaviors; they force your subclasses to provide others. For example, if you have an application framework, an abstract class may provide default services such as event and message handling. Those services allow your application to plug in to your application framework. However, there is some application-specific functionality that only your application can perform. Such functionality might include startup and shutdown tasks, which are often application-dependent. So instead of trying to define that behavior itself, the abstract base class can declare abstract shutdown and startup methods. The base class knows that it needs those methods, but an abstract class lets your class admit that it doesn't know how to perform those actions; it only knows that it must initiate the actions. When it is time to start up, the abstract class can call the startup method. When the base class calls this method, Java calls the method defined by the child class.

Many developers forget that a class that defines an abstract method can call that method as well. Abstract classes are an excellent way to create planned inheritance hierarchies. They're also a good choice for nonleaf classes in class hierarchies.

The definition of the abstract class may describe code and state, and classes that derive from them may not derive from other classes at the same time. That's what the technical difference is.

Therefore, from the point of view of usage & philosophy, the difference is that by setting up an abstract class, you constrain any other functionality that the objects of that class may implement, and provide those objects with some basic functionality that is common for any such object (which is a kind of constraint, too), while by setting up an interface, you set up no constraints for other functionality and make no real-code provisions for that functionality which you have in mind. Use the abstract classes when you about know everything that objects of this class are supposed to be doing for the benefit of their users. Use the interfaces when the objects might also do something else that you can't even guess by now.

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