Nice programing

추상 클래스 vs. 인터페이스 vs. 믹스 인

nicepro 2020. 11. 11. 20:39
반응형

추상 클래스 vs. 인터페이스 vs. 믹스 인


누군가 추상 클래스 , 인터페이스믹스 인 간의 차이점을 설명해 주 시겠습니까? 이전에 코드에서 각각을 사용했지만 기술적 차이점을 모릅니다.


추상 클래스

추상 클래스는 인스턴스화되도록 설계되지 않은 클래스입니다. 추상 클래스는 구현이 없거나 일부 구현 또는 모든 구현을 가질 수 있습니다. 추상 클래스는 하위 클래스가 공통 (기본) 구현을 공유 할 수 있도록 설계되었습니다. 추상 클래스의 (의사 코딩 된) 예제는 다음과 같습니다.

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 # 은 다중 상속을 허용하는 언어에서 발견 되는 Deadly Diamond of Death 문제에 대한 해결 방법으로 인터페이스를 사용 합니다 (올바르게 처리하면 실제로는 그렇게 치명적이지 않습니다).

Mixin

믹스 인 (때로 ​​트레이 트라고도 함)은 추상 클래스의 다중 상속을 허용합니다. Mixins는 C ++ 광기로 인해 다중 상속이 갖는 무서운 연관성이 없기 때문에 사람들이 더 편하게 사용할 수 있습니다. 그들은 똑같은 Deadly Diamond of Death 문제를 가지고 있지만, 그들을 지원하는 언어는 C ++보다 더 우아한 방법으로 그것을 완화하므로 더 나은 것으로 인식됩니다.

믹스 인은 행동 재사용 , 더 유연한 인터페이스 및 더 강력한 인터페이스를 갖춘 인터페이스 로 환영받습니다 . 이들 모두 interface에 Java 및 C # 키워드를 참조 하는 용어가 있음을 알 수 있습니다. 믹스 인은 인터페이스가 아닙니다. 다중 상속입니다. 더 예쁜 이름으로.

믹스 인이 나쁘다는 말은 아닙니다. 다중 상속은 나쁘지 않습니다. 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 이후 믹스 인을 지원했다는 것입니다. 인터페이스의 확장 메서드를 사용하여 수행 할 수 있습니다. 다음은 real (!) C # 코드 믹스 인 스타일을 사용한 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());
        }
    }
}

일반적으로 :

인터페이스는 작업을 지정하는 계약이지만, 어떤 구현하지 않고. 일부 언어 (Java, C #)는 인터페이스에 대한 지원 기능이 내장되어 있고 다른 언어에서는 '인터페이스'가 C ++의 순수 가상 클래스와 같은 규칙을 설명합니다.

추상 클래스는 구현하지 않고 적어도 하나 개의 동작을 지정하는 클래스입니다. 추상 클래스는 구현의 일부를 제공 할 수도 있습니다. 다시 말하지만, 일부 언어는 클래스를 추상으로 표시하는 지원 기능이 내장되어 있으며 다른 언어에서는 암시 적입니다. 예를 들어, C ++에서 순수 가상 메서드를 정의하는 클래스는 추상입니다.

믹스 인은 서브 클래스에 쉽게 특정 기능의 구현을하도록 설계되어 있지만 그 자체로 사용할 수 있도록 설계되지 않는 클래스입니다. 예를 들어 요청을 처리하는 객체에 대한 인터페이스가 있다고 가정합니다.

interface RequestHandler {
  void handleRequest(Request request);
}

아마도 미리 정해진 수를 얻을 때까지 요청을 축적 한 다음 버퍼를 플러시하여 요청을 버퍼링하는 것이 유용 할 것입니다. 플러시 동작을 지정하지 않고 믹스 인으로 버퍼링 기능을 구현할 수 있습니다 .

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

이렇게하면 매번 버퍼링 기능을 다시 작성하지 않고도 디스크에 요청을 쓰고 웹 서비스를 호출하는 요청 핸들러를 쉽게 작성할 수 있습니다. 이러한 요청 처리기는 단순히 확장 할 수 있습니다 BufferedRequestHandlerMixin및 구현 flushBuffer.

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


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"


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.


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?


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

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

참고URL : https://stackoverflow.com/questions/918380/abstract-classes-vs-interfaces-vs-mixins

반응형