Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Abstract classes vs. interfaces vs. mixins

Could someone please explain to me the differences between abstract classes, interfaces, and mixins? I've used each before in my code but I don't know the technical differences.

like image 921
Sasha Chedygov Avatar asked May 27 '09 22:05

Sasha Chedygov


People also ask

Are abstract classes better than interfaces?

The short answer: An abstract class allows you to create functionality that subclasses can implement or override. An interface only allows you to define functionality, not implement it. And whereas a class can extend only one abstract class, it can take advantage of multiple interfaces.

What is the difference between a mixin and inheritance?

Mixins are sometimes described as being "included" rather than "inherited". In short, the key difference from an inheritance is that mix-ins does NOT need to have a "is-a" relationship like in inheritance. From the implementation point of view, you can think it as an interface with implementations.

What is the difference between a mixin and inheritance in Dart?

Mixins is not a way to get multiple inheritance in the classical sense. Mixins is a way to abstract and reuse a family of operations and state. It is similar to the reuse you get from extending a class, but it is compatible with single-inheritance because it is linear.

Why do we need Mixins?

Mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (the "diamond problem"), or to work around lack of support for multiple inheritance in a language. A mixin can also be viewed as an interface with implemented methods.


1 Answers

Abstract Class

An abstract class is a class that is not designed to be instantiated. Abstract classes can have no implementation, some implementation, or all implementation. Abstract classes are designed to allow its subclasses share a common (default) implementation. A (pseudocoded) example of an abstract class would be something like this

abstract class Shape {     def abstract area();  // abstract (unimplemented method)     def outline_width() = { return 1; }  // default implementation } 

A subclass might look like

class Rectangle extends Shape {     int height = width = 5;     def override area() = { return height * width; }  // implements abstract method     // no need to override outline_width(), but may do so if needed } 

Possible usage

def main() = {     Shape[] shapes = { new Rectangle(), new Oval() };     foreach (s in shapes) {         print("area: " + s.area() + ", outline width: " + s.outline_width());     } } 

If a subclass does not override unimplemented methods, it is also an abstract class.

Interface

In general computer science terms, an interface is the parts of a program exposed to a client. Public classes and members are examples of interfaces.

Java and C# have a special interface keyword. These are more or less an abstract class with no implementation. (There's trickiness about constants, nested classes, explicit implementation, and access modifiers that I'm not going to get into.) Though the part about "no implementation" doesn't fit any more in Java, they added default methods. The interface keyword can be seen as a reification of the interface concept.

Going back to the Shape example

interface Shape {     def area();  // implicitly abstract so no need for abstract keyword     def outline_width();  // cannot implement any methods }  class Rectangle implements Shape {     int height = width = 5;     def override area() = { return height * width; }     def override outline_width() = { return 1; }  // every method in interface must be implemented }  def main() = {     Shape[] shapes = { new Rectangle(), new Oval() };     foreach (s in shapes) {         print("area: " + s.area() + ", outline width: " + s.outline_width());     } } 

Java and C# do not allow multiple inheritance of classes with implementation, but they do allow multiple interface implementation. Java and C# use interfaces as a workaround to the Deadly Diamond of Death Problem found in languages that allow multiple inheritance (which isn't really that deadly, if properly handled).

Mixin

A mixin (sometimes called a trait) allows multiple inheritance of abstract classes. Mixins don't have the scary association that multiple inheritance has (due to C++ craziness), so people are more comfortable using them. They have the same exact Deadly Diamond of Death Problem, but languages that support them have more elegant ways of mitigating it than C++ has, so they're perceived as better.

Mixins are hailed as interfaces with behavioral reuse, more flexible interfaces, and more powerful interfaces. You will notice all these have the term interface in them, referring to the Java and C# keyword. Mixins are not interfaces. They are multiple inheritance. With a prettier name.

This is not to say that mixins are bad. Multiple inheritance isn't bad. The way C++ resolves multiple inheritance is what everyone gets all worked up about.

On to the tired, old Shape example

mixin Shape {     def abstract area();     def outline_width() = { return 1; } }  class Rectangle with Shape {     int height = width = 5;     def override area() = { return height * width; } }  def main() = {     Shape[] shapes = { new Rectangle(), new Oval() };     foreach (s in shapes) {         print("area: " + s.area() + ", outline width: " + s.outline_width());     } } 

You will notice there is no difference between this and the abstract class example.

One extra tidbit is that C# has supported mixins since version 3.0. You can do it with extension methods on interfaces. Here's the Shape example with real(!) C# code mixin style

interface Shape {     int Area(); }  static class ShapeExtensions {     public static int OutlineWidth(this Shape s)     {         return 1;     } }  class Rectangle : Shape {     int height = 5;     int width = 5;      public int Area()     {         return height * width;     } }  class Program {     static void Main()     {         Shape[] shapes = new Shape[]{ new Rectangle(), new Oval() };         foreach (var s in shapes)         {             Console.Write("area: " + s.Area() + ", outline width: " + s.OutlineWidth());         }     } } 
like image 80
Eva Avatar answered Sep 20 '22 15:09

Eva