Abstract classes vs. interfaces vs. mixins

2019-03-07 18:33发布

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.

7条回答
走好不送
2楼-- · 2019-03-07 18:36

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());
        }
    }
}
查看更多
男人必须洒脱
3楼-- · 2019-03-07 18:41

Basically an abstract class is an interface with some concrete implementation. An interface is just a contract that has no implementation detail.

You would use and abstract class if you want to create common functionality amoung all of the objects that implement the abstract class. Keeping with the DRY (Don't Repeat Yourself) principle of OOP.

查看更多
SAY GOODBYE
4楼-- · 2019-03-07 18:49

The meaning of 'Mixin' is excellently defined by Joshua Bloch in his effective Java book. An excerpt from the same book:

"mixin is a type that a class can implement in addition to its “primary type” to declare that it provides some optional behavior. For example, Comparable is a mixin interface that allows a class to declare that its instances are ordered with respect to other mutually comparable objects. Such an interface is called a mixin because it allows the optional functionality to be “mixed in” to the type’s primary functionality."

查看更多
Explosion°爆炸
5楼-- · 2019-03-07 18:53

Reference to Java and given example of Abstract class to provide mixin is misleading. First of all, Java does not support "mixins" by default. In Java terms abstract class and Mixins become confusing.

A mixin is a type that a class can implement in addition to its "primary type" to indicate that it provides some optional behavior. To speak in Java terms, one example would be your business value object implementing Serializable.

Josh Bloch says - "Abstract classes can not be used to define mixins - since a class can not have more than one parent" ( Remember Java allows only one "extends" candidate)

Look for languages like Scala and Ruby for appropriate implementation of the notion of "mixin"

查看更多
我欲成王,谁敢阻挡
6楼-- · 2019-03-07 18:53

An abstract class is a class that not all of its members are implemented ,they are left for the inheritors to be implemented.It forces its inheritors to implement its abstract members. Abstract classes can't be instantiated and thus their constructors shouldn't be public.]

Here's an example in C#:

    public abstract class Employee
    {
        protected Employee(){} 
        public abstract double CalculateSalary(WorkingInfo workingInfo);//no implementation each type of employee should define its salary calculation method.
    }

   public class PartTimeEmployee:Employee
  {
    private double _workingRate;
    public Employee(double workingRate)
    {
     _workingRate=workingRate;
    }
    public override double CalculateSalary(WorkingInfo workingInfo)
    {
      return workingInfo.Hours*_workingRate;
    }

}

An interface is a contract to be implemented by a class.It just declare the signature of the members of an implementing class and it has no implementation itself.We usually use interfaces to implement polymorphism,and to decouple dependent classes.

Here's an example in C#:

public interface IShape
{
int X{get;}
int Y{get;}
void Draw();
}

public class Circle:IShape
{
public int X{get;set;}
public int Y{get;set;}

public void Draw()
{
//Draw a circle
}
}

public class Rectangle:IShape
{
public int X{get;set;}
public int Y{get;set;}

public void Draw()
{
//Draw a rectangle
}
}
查看更多
等我变得足够好
7楼-- · 2019-03-07 18:59

Since many of guys have explained about the definitions and usage, I would like to highlight only important points

Interface:

  1. To define a contract ( preferably stateless - I mean no variables )
  2. To link unrelated classes with "has a" capabilities.
  3. To declare public constant variables (immutable state)

Abstract class:

  1. Share code among several closely related classes. It establishes "is a" relation.

  2. Share common state among related classes ( state can be modified in concrete classes)

I am closing the difference with a small example.

Animal can be an abstract class. Cat and Dog, extending this abstract class establishes "is a" relation.

Cat is a Animal

Dog is a Animal.

Dog can implement Bark interface. Then Dog has a capability of Barking.

Cat can implement Hunt interface. Then Cat has a capability of Hunting.

Man, who is not Animal, can implement Hunt interface. Then Man has a capability of Hunting.

Man and Animal (Cat/Dog) are unrelated. But Hunt interface can provide same capability to unrelated entities.

Mixin:

  1. If you want a mixture of both abstract class and interface. Especially useful when you want to force a new contract on many unrelated classes where some of them have to re-define new behaviour and some of them should stick to common implementation. Add common implementation in Mixin and allow other classes to re-define the contract methods if needed

If I want to declare an abstract class, I will follow one of these two approaches.

  1. Move all abstract methods to interface and my abstract class implements that interface.

    interface IHunt{
        public void doHunting();
    }
    abstract class Animal implements IHunt{
    
    }
    class Cat extends Animal{
        public void doHunting(){}
    }
    

Related SE question :

What is the difference between an interface and abstract class?

查看更多
登录 后发表回答