Abstract class vs Interface


Hum ni ngồi rảnh rảnh đọc cái Design Pattern , lâu lắm rồi ko đọc nó. Thì thấy ra mình còn đang confused giữa Abstract Class Interface .

Sau 1 hồi tìm hiểu trên net thì túm lại là tìm ra được 1 số câu hỏi và câu trả lời sau:

  1. Sự Giống và khác nhau giữa Interface và Abstract Class
  2. Khi nào thì dùng Abstract Class
  3. Khi nào thì dùng interface

Dươí đây là 1 đống tài liệu sau khi tổng kết, làm biếng dịch sang tiếng Việt (Và cũng không biết để sao) nên để vậy lun

What is an Abstract class?

An abstract class is a special kind of class that cannot be instantiated. So the question is why we need a class that cannot be instantiated? An abstract class is only to be sub-classed (inherited from). In other words, it only allows other classes to inherit from it but cannot be instantiated. The advantage is that it enforces certain hierarchies for all the subclasses. In simple words, it is a kind of contract that forces all the subclasses to carry on the same hierarchies or standards.

What is an Interface?

An interface is not a class. It is an entity that is defined by the word Interface. An interface has no implementation; it only has the signature or in other words, just the definition of the methods without the body . As one of the similarities to Abstract class, it is a contract that is used to define hierarchies for all subclasses or it defines specific set of methods and their arguments . The main difference between them is that a class can implement more than one interface but can only inherit from one abstract class . Since C# doesn’t support multiple inheritance, interfaces are used to implement multiple inheritance.

Both together

When we create an interface, we are basically creating a set of methods without any implementation that must be overridden by the implemented classes. The advantage is that it provides a way for a class to be a part of two classes: one inheritance hierarchy and one from the interface.

When we create an abstract class, we are creating a base class that might have one or more completed methods but at least one or more methods are left uncompleted and declared abstract . If all the methods of an abstract class are uncompleted then it is the same as an interface but with the restriction that it cannot make a class inherit from it. The purpose of an abstract class is to provide a base class definition for how a set of derived classes will work and then allow the programmers to fill the implementation in the derived classes.

There are some similarities and differences between an interface and an abstract class that I have arranged in a table for easier comparison:

Feature Interface Abstract class
Multiple inheritance A class may inherit several interfaces. A class may inherit only one abstract class.
Default implementation An interface cannot provide any code, just the signature. An abstract class can provide complete, default code and/or just the details that have to be overridden.
Constants Static final constants only, can use them without qualification in classes that implement the interface . On the other paw, these unqualified names pollute the namespace. You can use them and it is not obvious where they are coming from since the qualification is optional. Both instance and static constants are possible.
Third party convenience An interface implementation may be added to any existing third party class. A third party class must be rewritten to extend only from the abstract class.
is-a vs -able or can-do Interfaces are often used to describe the peripheral abilities of a class, not its central identity, e.g. an Automobile class might implement the Recyclable interface , which could apply to many otherwise totally unrelated objects. An abstract class defines the core identity of its descendants. If you defined a Dog abstract class then Damamation descendants are Dogs, they are not merely dogable. Implemented interfaces enumerate the general things a class can do, not the things a class is.In a Java context, users should typically implement the Runnable interface rather than extending Thread , because they’re not really interested in providing some new Thread functionality, they normally just want some code to have the capability of running independently. They want to create something that can be run in a thread, not a new kind of thread.The similar is-a vs has-a debate comes up when you decide to inherit or delegate.
Plug-in You can write a new replacement module for an interface that contains not one stick of code in common with the existing implementations. When you implement the inteface, you start from scratch without any default implementation. You have to obtain your tools from other classes; nothing comes with the interface other than a few constants. This gives you freedom to implement a radically different internal design. You must use the abstract class as-is for the code base, with all its attendant baggage, good or bad. The abstract class author has imposed structure on you. Depending on the cleverness of the author of the abstract class, this may be good or bad.
Core VS Peripheral Interfaces are used to define the peripheral abilities of a class. In other words both Human and Vehicle can inherit from a IMovable interface. An abstract class defines the core identity of a class and there it is used for objects of the same type.
Maintenance If your client code talks only in terms of an interface , you can easily change the concrete implementation behind it, using a factory method . Just like an interface , if your client code talks only in terms of an abstract class, you can easily change the concrete implementation behind it, using a factory method .
Homogeneity If the various implementations only share method signatures then it is better to use Interface. If the various implementations are of the same kind and use common behaviour or status then abstract class is better to use.
Speed Requires more time to find the actual method in the corresponding classes. Fast
Terseness The constant declarations in an interface are all presumed public static final , so you may leave that part out. You can’t call any methods to compute the initial values of your constants. You need not declare individual methods of an interface abstract . They are all presumed so. You can put shared code into an abstract class, where you cannot into an interface . If interfaces want to share code, you will have to write other bubblegum to arrange that. You may use methods to compute the initial values of your constants and variables, both instance and static. You must declare all the individual methods of an abstract class abstract .

Class vs. interface

Some say you should define all classes in terms of interfaces, but I think recommendation seems a bit extreme. I use interfaces when I see that something in my design will change frequently .

For example , the Strategy pattern lets you swap new algorithms and processes into your program without altering the objects that use them. A media player might know how to play CDs, MP3s, and wav files. Of course, you don’t want to hardcode those playback algorithms into the player; that will make it difficult to add a new format like AVI. Furthermore, your code will be littered with useless case statements. And to add insult to injury, you will need to update those case statements each time you add a new algorithm. All in all, this is not a very object-oriented way to program.

With the Strategy pattern, you can simply encapsulate the algorithm behind an object. If you do that, you can provide new media plug-ins at any time. Let’s call the plug-in class MediaStrategy . That object would have one method: playStream(Stream s) . So to add a new algorithm, we simply extend our algorithm class. Now, when the program encounters the new media type, it simply delegates the playing of the stream to our media strategy. Of course, you’ll need some plumbing to properly instantiate the algorithm strategies you will need.

This is an excellent place to use an interface. We’ve used the Strategy pattern, which clearly indicates a place in the design that will change. Thus, you should define the strategy as an interface. You should generally favor interfaces over inheritance when you want an object to have a certain type; in this case, MediaStrategy . Relying on inheritance for type identity is dangerous; it locks you into a particular inheritance hierarchy. Java doesn’t allow multiple inheritance, so you can’t extend something that gives you a useful implementation or more type identity.

Interface vs. abstract class

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.

When To Use Interfaces

An interface allows somebody to start from scratch to implement your interface or implement your interface in some other code whose original or primary purpose was quite different from your interface . To them, your interface is only incidental, something that have to add on to the their code to be able to use your package.

When To Use Abstract classes

An abstract class, in contrast, provides more structure. It usually defines some default implementations and provides some tools useful for a full implementation. The catch is, code using it must use your class as the base. That may be highly inconvenient if the other programmers wanting to use your package have already developed their own class hierarchy independently. In Java, a class can inherit from only one base class.

When to Use Both

You can offer the best of both worlds, an interface and an abstract class. Implementors can ignore your abstract class if they choose. The only drawback of doing that is calling methods via their interface name is slightly slower than calling them via their abstract class name.