抽象类、接口、mixins

发布于 2024-07-23 10:03:04 字数 113 浏览 3 评论 0原文

有人可以向我解释一下抽象类接口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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

内心旳酸楚 2024-07-30 10:03:04

抽象类

抽象类是不被设计为实例化的类。 抽象类可以没有实现、部分实现或全部实现。 抽象类旨在允许其子类共享公共(默认)实现。 抽象类的(伪编码)示例如下

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

所示 子类可能看起来像

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
}

可能的用法

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

如果子类不重写未实现的方法,那么它也是一个抽象类。

接口

在一般计算机科学术语中,接口是暴露给客户端的程序的一部分。 公共类和成员是接口的示例。

Java 和 C# 有一个特殊的interface 关键字。 这些或多或少是一个没有实现的抽象类。 (常量、嵌套类、显式实现和访问修饰符有些棘手,我不打算深入讨论。)尽管“无实现”部分不再适合 Java,但他们添加了默认方法。 interface 关键字可以看作是接口概念的具体化。

回到 Shape 示例,

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 和 C# 不允许具有实现的类的多重继承,但它们确实允许多个接口实现。 Java 和 C# 使用接口来解决以下语言中发现的致命钻石死亡问题允许多重继承(如果处理得当,这并不是那么致命)。

Mixin

Mixin(有时称为特征)允许抽象类的多重继承。 Mixin 没有多重继承所具有的可怕关联(由于 C++ 的疯狂),因此人们更愿意使用它们。 它们具有完全相同的致命钻石死亡问题,但支持它们的语言比 C++ 拥有更优雅的缓解方法,因此它们被认为更好。

Mixin 被誉为具有行为重用的接口, 更灵活接口,和更强大的界面。 您会注意到所有这些都包含术语interface,指的是Java 和C# 关键字。 Mixin 不是接口。它们是多重继承。 有了一个更漂亮的名字。

这并不是说 mixin 不好。 多重继承并不坏。 C++ 解决多重继承的方式是每个人都兴奋不已的问题。

继续看陈旧的 Shape 示例,

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());
    }
}

您会发现这与抽象类示例没有区别。

额外的一点是,C# 从 3.0 版本开始就支持 mixin。 您可以使用接口上的扩展方法来完成此操作。 这是具有真实(!)C# 代码 mixin 风格的 Shape 示例

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());
        }
    }
}

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());
        }
    }
}
半岛未凉 2024-07-30 10:03:04

一般来说:

接口是一个指定操作的契约,但没有任何实现。 某些语言(Java、C#)内置了对接口的支持,而在其他语言中,“接口”描述了一种约定,如 C++ 中的纯虚拟类。

抽象类是一种指定至少一个操作但没有实现的类。 抽象类还可以提供其实现的某些部分。 同样,某些语言内置了对将类标记为抽象的支持,而在其他语言中它是隐式的。 例如,在 C++ 中,定义纯虚方法的类是抽象的。

mixin 是一个类,其设计目的是使子类中某些功能的实现变得更容易,但其本身并不设计为使用。 例如,假设我们有一个处理请求的对象的接口,

interface RequestHandler {
  void handleRequest(Request request);
}

也许通过累积请求来缓冲请求直到我们有一些预定的数量,然后刷新缓冲区会很有用。 我们可以使用 mixin 实现缓冲功能,而不需要指定刷新行为:

abstract class BufferedRequestHandlerMixin implements RequestHandler {
  List<Request> buffer = new List<Request>();

  void handleRequest(Request request) {
    buffer.add(request);

    if (buffer.size == BUFFER_FLUSH_SIZE) {
        flushBuffer(buffer);
        buffer.clear();
    }
  }

  abstract void flushBuffer(List<Request> buffer);
}

这样,我们就可以轻松编写一个请求处理程序,将请求写入磁盘、调用 Web 服务等,而无需重写每次都缓冲功能。 这些请求处理程序可以简单地扩展BufferedRequestHandlerMixin并实现flushBuffer

mixin 的另一个很好的例子是 Spring 中的众多支持类之一,即。 HibernateDaoSupport

In general:

An interface is a contract specifying operations, but without any implementation. Some languages (Java, C#) have baked-in support for interfaces, and in others 'interface' describes a convention like a pure virtual class in C++.

An abstract class is a class which specifies at least one operation without an implementation. Abstract classes can also provide some parts of their implementation. Again, some languages have baked-in support for marking classes as abstract and it is implicit in others. For example, in C++ a class which defines a pure virtual method is abstract.

A mixin is a class which is designed to make implementation of certain functionality easier in subclasses, but which is not designed to be used by itself. For example, say that we have an interface for an object that handles requests

interface RequestHandler {
  void handleRequest(Request request);
}

Perhaps it would be useful to buffer the requests by accumulating them until we have some predetermined number and then flushing the buffer. We can implement the buffering functionality with a mixin without specifying the flush behavior:

abstract class BufferedRequestHandlerMixin implements RequestHandler {
  List<Request> buffer = new List<Request>();

  void handleRequest(Request request) {
    buffer.add(request);

    if (buffer.size == BUFFER_FLUSH_SIZE) {
        flushBuffer(buffer);
        buffer.clear();
    }
  }

  abstract void flushBuffer(List<Request> buffer);
}

This way, it's easy for us to write a request handler that writes requests to disk, calls a web service, etc. without rewriting the buffering functionality each time. These request handlers can simply extend BufferedRequestHandlerMixin and implement flushBuffer.

Another good example of a mixin is one of the many support classes in Spring, viz. HibernateDaoSupport.

深海夜未眠 2024-07-30 10:03:04

由于许多人已经解释了定义和用法,我只想强调重要的一点

接口:

  1. 定义合约(最好是无状态的 - 我的意思是没有变量)
  2. 用“具有”功能。
  3. 声明公共常量变量(不可变状态)

抽象类:

  1. 在几个密切相关的类之间共享代码。 它建立了“is a”关系。

  2. 在相关类之间共享公共状态(可以在具体类中修改状态)

我用一个小例子来结束差异。

Animal 可以是一个抽象类。 CatDog,扩展这个抽象类建立了“is a”关系。

是一种动物

是一种动物。

Dog 可以实现Bark接口。 那么狗具有吠叫的能力。

Cat 可以实现Hunt接口。 那么猫具有狩猎的能力。

不是动物,可以实现Hunt接口。 那么人类就有了狩猎的能力。

人与动物(猫/狗)没有关系。 但Hunt接口可以为不相关的实体提供相同的能力。

Mixin:

  1. 如果您想要抽象类接口的混合。 当您想要在许多不相关的类上强制执行新契约时特别有用,其中一些类必须重新定义新行为,而其中一些应该坚持通用实现。 在 Mixin 中添加通用实现,并允许其他类在需要时重新定义契约方法。

如果我想声明一个抽象类,我将遵循这两种方法之一。

  1. 将所有抽象方法移至接口,我的抽象类实现该接口。

    接口 IHunt{ 
          公共无效 doHunting(); 
      } 
      抽象类 Animal 实现 IHunt{ 
    
      } 
      类 Cat 扩展了 Animal{ 
          公共无效 doHunting(){} 
      } 
      

相关SE问题:

有什么区别接口和抽象类之间?

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?

尬尬 2024-07-30 10:03:04

对 Java 的引用以及提供 mixin 的抽象类示例具有误导性。
首先,Java默认不支持“mixins”。 在 Java 术语中,抽象类和 Mixins 变得令人困惑。

mixin 是类除了其“主要类型”之外还可以实现的一种类型,以指示它提供一些可选行为。 用 Java 术语来说,一个例子是实现可序列化的业务价值对象。

Josh Bloch 说 - “抽象类不能用于定义 mixins - 因为一个类不能有多个父类”(记住 Java 只允许一个“扩展”候选者)

寻找 Scala 和 Ruby 等语言来适当实现这一概念“混合”的

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"

獨角戲 2024-07-30 10:03:04

Joshua Bloch 在他的 Java 著作中对“Mixin”的含义进行了出色的定义。 同一本书的摘录:

“mixin 是一种类型
除了其“主要类型”之外,类还可以实现以声明它提供
一些可选的行为。 例如,Comparable 是一个 mixin 接口,
允许一个类声明其实例相对于其他实例是相互排序的
可比较的对象。 这样的接口称为 mixin,因为它允许
要“混合”到类型的主要功能中的可选功能。”

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

莫言歌 2024-07-30 10:03:04

基本上,抽象类是具有一些具体实现的接口。 接口只是一个没有实现细节的契约。

如果您想在实现抽象类的所有对象之间创建通用功能,则可以使用抽象类。 遵守 OOP 的 DRY(不要重复自己)原则。

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.

难以启齿的温柔 2024-07-30 10:03:04

抽象类是一个类,它的所有成员都没有被实现,它们留给继承者去实现。它强制它的继承者实现它的抽象成员。
抽象类不能实例化,因此它们的构造函数不应该是公共的。]

这是 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;
    }

}

接口是由类实现的契约。它只是声明实现类的成员的签名,并且它本身没有实现。我们通常使用接口来实现多态性,并解耦依赖的类。

下面是一个 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
}
}

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
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文