Groovy의 특성 소개

1. 개요

이 자습서에서는 Groovy의 특성 개념을 살펴 보겠습니다. Groovy 2.3 릴리스에서 도입되었습니다.

2. 특성은 무엇입니까?

특성은 여러 클래스의 기능을 확장하는 데 사용할 수있는 일련의 메서드 또는 동작을 나타내는 재사용 가능한 구성 요소입니다.

이러한 이유로 기본 구현과 상태를 모두 전달하는 인터페이스로 간주됩니다. 모든 특성은 trait 키워드를 사용하여 정의됩니다 .

3. 방법

A의 방법 선언 특성은 클래스에 정규 방법을 선언 유사하다. 그러나 우리는 trait 에서 protected 또는 package-private 메서드를 선언 할 수 없습니다 .

공개 및 비공개 메소드가 어떻게 구현되는지 살펴 보겠습니다.

3.1. 공개 방법

시작하기 위해 우리는 퍼블릭 메서드가 트레이 트에서 어떻게 구현 되는지 살펴볼 것 입니다.

UserTrait 이라는 특성공용 sayHello 메서드를 만들어 보겠습니다 .

trait UserTrait { String sayHello() { return "Hello!" } }

그런 다음 UserTrait 를 구현 하는 Employee 클래스를 생성합니다 .

class Employee implements UserTrait {}

이제 Employee 인스턴스가 UserTrait 의 sayHello 메서드에 액세스 할 수 있는지 확인하는 테스트를 만들어 보겠습니다 .

def 'Should return msg string when using Employee.sayHello method provided by User trait' () { when: def msg = employee.sayHello() then: msg msg instanceof String assert msg == "Hello!" }

3.2. 개인 방법

트레이 트에 private 메서드를 만들고 다른 public 메서드 에서 참조 할 수도 있습니다 .

UserTrait 에서 코드 구현을 살펴 보겠습니다 .

private String greetingMessage() { return 'Hello, from a private method!' } String greet() { def msg = greetingMessage() println msg return msg } 

구현 클래스 의 private 메서드에 액세스하면 MissingMethodException이 발생합니다 .

def 'Should return MissingMethodException when using Employee.greetingMessage method' () { when: def exception try { employee.greetingMessage() } catch(Exception e) { exception = e } then: exception exception instanceof groovy.lang.MissingMethodException assert exception.message == "No signature of method: com.baeldung.traits.Employee.greetingMessage()" + " is applicable for argument types: () values: []" }

A의 특성, 개인 방법은 다른 공공 방법으로 필요하지만, 모든 클래스에 의해 오버라이드 (override)하지 말아야 어떤 구현을 위해 필수적 일 수 있습니다.

3.3. 추상 방법

특성은 또한 포함 할 수 있습니다 추상적 다음 다른 클래스에서 구현 될 수있는 방법을 :

trait UserTrait { abstract String name() String showName() { return "Hello, ${name()}!" } }
class Employee implements UserTrait { String name() { return 'Bob' } } 

3.4. 기본 메서드 재정의

일반적으로 트레이 트는 퍼블릭 메서드의 기본 구현을 포함하지만 구현 클래스에서 재정의 할 수 있습니다.

trait SpeakingTrait { String speak() { return "Speaking!!" } } 
class Dog implements SpeakingTrait { String speak() { return "Bow Bow!!" } } 

특성은 보호개인 범위를 지원하지 않습니다 .

4. 키워드

this 키워드 의 동작은 Java 의 동작 과 유사합니다. 우리는 특성슈퍼 클래스 로 간주 할 수 있습니다 .

예를 들어, 우리는 반환하는 방법 만듭니다 A의 특성을 :

trait UserTrait { def self() { return this } }

5. 인터페이스

특성은 또한 정규 수업이 할 것처럼 인터페이스를 구현할 수 있습니다.

인터페이스를 만들고 이를 트레이 트에 구현해 보겠습니다 .

interface Human { String lastName() }
trait UserTrait implements Human { String showLastName() { return "Hello, ${lastName()}!" } }

이제 구현 클래스에서 인터페이스추상 메서드를 구현해 보겠습니다 .

class Employee implements UserTrait { String lastName() { return "Marley" } }

6. 속성

일반 클래스 에서처럼 특성 에 속성을 추가 할 수 있습니다 .

trait UserTrait implements Human { String email String address }

7. 특성 확장

Similar to a regular Groovy class, a trait may extend another trait using the extends keyword:

trait WheelTrait { int noOfWheels } trait VehicleTrait extends WheelTrait { String showWheels() { return "Num of Wheels $noOfWheels" } } class Car implements VehicleTrait {}

We can also extend multiple traits with the implements clause:

trait AddressTrait { String residentialAddress } trait EmailTrait { String email } trait Person implements AddressTrait, EmailTrait {}

8. Multiple Inheritance Conflicts

When a class implements two or more traits that have methods with the same signature, we need to know how to resolve the conflicts. Let's look at how Groovy resolves such conflicts by default, as well as a way that we can override the default resolution.

8.1. Default Conflict Resolution

By default, the method from the last declared trait in the implements clause will be picked up.

Therefore, traits help us to implement multiple inheritances without encountering the Diamond Problem.

First, let's create two traits with a method having the same signature:

trait WalkingTrait { String basicAbility() { return "Walking!!" } } trait SpeakingTrait { String basicAbility() { return "Speaking!!" } } 

Next, let's write a class that implements both traits:

class Dog implements WalkingTrait, SpeakingTrait {} 

Because SpeakingTrait is declared last, its basicAbility method implementation would be picked up by default in the Dog class.

8.2. Explicit Conflict Resolution

Now, if we don't want to simply take the default conflict resolution provided by the language, we can override it byexplicitly choosing which method to call using the trait.super.method reference.

For instance, let's add another method with the same signature to our two traits:

String speakAndWalk() { return "Walk and speak!!" }
String speakAndWalk() { return "Speak and walk!!" }

Now, let's override the default resolution of multiple inheritance conflicts in our Dog class using the super keyword:

class Dog implements WalkingTrait, SpeakingTrait { String speakAndWalk() { WalkingTrait.super.speakAndWalk() } }

9. Implementing Traits at Runtime

To implement a trait dynamically, we can use the as keyword to coerce an object to a trait at runtime.

For instance, let’s create an AnimalTrait with the basicBehavior method:

trait AnimalTrait { String basicBehavior() { return "Animalistic!!" } }

To implement several traits at once, we can use the withTraits method instead of the as keyword:

def dog = new Dog() def dogWithTrait = dog.withTraits SpeakingTrait, WalkingTrait, AnimalTrait

10. Conclusion

In this article, we've seen how to create traits in Groovy and explored some of their useful features.

특성은 우리의 수업을 통해 일반적인 구현 및 기능을 추가하는 정말 효과적인 방법입니다. 또한 중복 코드를 최소화하고 코드 유지 관리를 더 쉽게 할 수 있습니다.

평소처럼이 기사의 코드 구현 및 단위 테스트는 GitHub에서 사용할 수 있습니다.