IT TIP

Groovy에서 @Delegate, @Mixin 및 Traits의 차이점은 무엇입니까?

itqueen 2021. 1. 6. 20:34
반응형

Groovy에서 @Delegate, @Mixin 및 Traits의 차이점은 무엇입니까?


누군가 내가 Groovy Traits vs. Mixins (@Mixin) vs. Delegates (@Delegate) 를 사용하고 싶을 때 설명 할 수 있습니까? 아마도 몇 가지 절충안과 디자인 문제가 도움이 될 것입니다.

그것들은 모두 행동의 여러 "클래스"를 재사용하는 것을 허용하는 것 같습니다. 감사. :-)

이 SO 스레드도 도움이되었습니다 : Groovy에서 @Delegate와 @Mixin AST 변환의 차이점


동의합니다. 그들은 모두 행동의 여러 "클래스"를 재사용하는 것을 허용하는 것 같습니다. 그러나 차이점이 있으며이를 이해하면 결정에 도움이 될 것입니다.

각 기능에 대한 간략한 요약 / 강조 표시와 적절한 사용 예를 제공하기 전에 각각의 결론을 요약 해 보겠습니다.

결론 / 일반적인 사용법 :

  • @Delegate : 델리게이트 클래스의 모든 기능을 추가하는 데 사용되지만 여전히 실제 구현과 밀접하게 연결되는 것을 피합니다. 상속보다 구성 을 달성합시다 .
  • @Mixin : groovy 2.3에서 더 이상 사용되지 않습니다. 하나 이상의 클래스에서 클래스에 메서드를 추가하는 간단한 방법입니다. 벌레에 휩싸인
  • 런타임 믹스 인이 :에 하나 이상의 방법을 추가 어떤 예를 들어 JDK 또는 제 3 자 라이브러리에서 클래스, 기존 클래스.
  • 특성 : 그루비 2.3의 새로운 기능. 클래스에 하나 이상의 특성을 추가하는 잘 정의 된 방법. @Mixin을 대체합니다. 추가 된 메소드는 Java 클래스에서 볼 수있는 유일한 것입니다.

이제 각각에 대해 좀 더 자세히 살펴 보겠습니다.

@대리자

상속은 많은 경우에 과도하게 사용됩니다. 즉, 종종 부적절하게 사용됩니다. Java의 고전적인 예는 입력 스트림, 판독기 또는 컬렉션 클래스를 확장하는 것입니다. 대부분의 경우 상속을 사용하는 것은 구현과 너무 밀접하게 연결되어 있습니다. 즉, 실제 구현은 공용 메서드 중 하나가 실제로 다른 메서드를 사용하도록 작성됩니다. 둘 다 재정의하고을 호출 super하면 원치 않는 부작용이 발생할 수 있습니다. 이후 버전에서 구현이 변경되면 처리 방법도 업데이트해야합니다.

대신 상속보다 합성 을 사용하도록 노력해야합니다 .

예 : 목록에 추가 된 요소를 계산하는 계산 목록 :

class CountingList<E> {
    int counter = 0
    @Delegate LinkedList<E> list = new LinkedList<>()
    boolean addAll(Collection<? extends E> c) {
        counter += c.size()
        list.addAll(c)
    }
    boolean addAll(int index, Collection<? extends E> c) {
        counter += c.size()
        list.addAll(index, c)
    }
    // more add methods with counter updates
}

이 예제에서는 @Delegate"있는 그대로"남겨 두려는 모든 공용 메서드에 대한 지루한 표준 코드를 모두 제거합니다. 즉, 단순히 호출을 기본 목록으로 전달하는 메서드가 추가됩니다. 또한 CountingList이 메서드는 구현과 분리되어 있으므로 이러한 메서드 중 하나가 다른 메서드를 호출하여 구현되는지 여부를 신경 쓸 필요가 없습니다. 위의 예에서 실제로는을 LinkedList.add(Collection)호출 LinkedList.add(int, Collection)하기 때문에 상속을 사용하여 구현하는 것이 간단하지 않습니다.

요약:

  • 위임 된 개체의 모든 공용 메서드에 대한 기본 구현을 제공합니다.
    • 명시 적으로 추가 된 동일한 서명이있는 메서드가 우선합니다.
  • 암시 적으로 추가 된 메서드는 Java에서 볼 수 없습니다 .
  • @Delegate하나의 클래스 에 여러를 추가 할 수 있습니다 .
    • 하지만 그렇게한다면 그것이 정말로 바람직한 지 고려해야합니다.
    • 무엇에 대한 다이아몬드 문제 , 즉 동일한 서명 대의원 여러 방법이 있다면?
  • 대리자가있는 클래스 ( CountingList위 예에서)는 대리자 클래스의 인스턴스가 아닙니다.
    • CountingList, LinkedList.
  • 상속을 통한 긴밀한 결합을 피하기 위해 사용합니다.

@Mixin

@Mixin변환으로 인해 다가오는 특징 지원에, 그루비 2.3 이상 사용되지 않습니다. 이것은으로 할 수있는 모든 것이 @Mixin대신 특성으로 할 수 있어야 한다는 힌트를 제공합니다 .

제 경험상 @Mixin일종의 혼합 된 축복입니다. :)

핵심 개발자의 입장에서 "해결하기 어려운"버그로 가득 찬 버그입니다. 그것과는 거리가 먼 "쓸모 없다"는 말은 아닙니다. 그러나 그루비 2.3을 사용하거나 기다릴 기회가 있다면 대신 특성을 사용해야합니다.

AST 변환이하는 일은 단순히 한 클래스에서 다른 클래스로 메서드를 추가하는 것입니다. 예를 들면 :

class First {
    String hello(String name) { "Hello $name!" }
}

@Mixin(First)
class Second {
    // more methods
}

assert new Second().hello('Vahid') == 'Hello Vahid!'

요약:

  • 한 클래스의 메서드를 다른 클래스에 추가합니다.
  • 한 클래스에서 다른 클래스로 간단한 메서드 추가를 위해 groovy <2.3에서 사용
    • "슈퍼"클래스에 추가하지 마십시오 (적어도 문제가있었습니다)
  • 벌레에 휩싸인
  • Groovy 2.3에서 사용되지 않음
  • 암시 적으로 추가 된 메서드는 Java에서 볼 수 없습니다 .
  • 다른 클래스가 혼합 된 클래스는 다른 클래스의 인스턴스가 아닙니다.
    • Second, 인스턴스가 아닙니다First
  • You can mix in several classes into one other class
    • what about the diamond problem, i.e. if you have methods in the mixed in classes with the same signature?
  • Use as a simple method of adding the functionality of one class into another in groovy <2.3

Runtime mixin

Runtime mixins and the @Mixin transform are quite different, they solve different use-cases and are used in totally different situations. Since they have the same name, it's easy to confuse one with the other, or to think that they are one and the same. Runtime mixins, however, are not deprecated in groovy 2.3.

I tend to think about runtime mixins as the way to add methods to existing classes, such as any class in the JDK. It's the mechanism used by Groovy to add extra methods to the JDK.

Example:

class MyStringExtension {
    public static String hello(String self) {
        return "Hello $self!"
    }
}

String.mixin(MyStringExtension)

assert "Vahid".hello() == 'Hello Vahid!'

Groovy also have a nice extension module feature, where you don't need to manually perform the mixin, instead groovy does it for you as long as it finds the module descriptor in the correct location in the classpath.

Summary:

  • Add methods to any existing class
    • any classes in the JDK
    • any 3rd party classes
    • or any of your own classes
  • Overrides any existing method with the same signature
  • Added methods are not visible in Java
  • Typically used to extend existing/3rd party classes with new functionality

Traits

Traits are new to groovy 2.3.

I tend to view these traits as something between the familiar interface and class. Something akin to a "light-weight" class. They are dubbed "interfaces with default implementations and state" in the documentation.

Traits are similar to the @Mixin transform that they replace, but they are also more powerful. For starters, they are much more well-defined. A trait cannot be instantiated directly, just like an interface, they need an implementing class. And a class may implement many traits.

A simple example:

trait Name {
    abstract String name()
    String myNameIs() { "My name is ${name()}!" }
}
trait Age {
    int age() { 42 }
}

class Person implements Name, Age {
    String name() { 'Vahid' }
}

def p = new Person()
assert p.myNameIs() == 'My name is Vahid!'
assert p.age() == 42
assert p instanceof Name
assert p instanceof Age

The immediate difference between traits and @Mixin is that trait is a language keyword, not an AST transform. Further, it can contain abstract methods that needs to be implemented by the class. Further, a class can implement several traits. The class implementing a trait is an instance of that trait.

Summary:

  • Traits provide an interface with implementation and state.
  • A class can implement multiple traits.
  • Methods implemented by a trait are visible in Java.
  • Compatible with type checking and static compilation.
  • Traits can implement interfaces.
  • Traits can not be instantiated by themselves.
  • A trait can extend another trait.
  • Handling of the diamond problem is well-defined.
  • Typical usage:
    • add similar traits to different classes.
      • (as an alternative to AOP)
    • compose a new class from several traits.

ReferenceURL : https://stackoverflow.com/questions/23121890/difference-between-delegate-mixin-and-traits-in-groovy

반응형