ProgramingTip

클로저 : 왜 그렇게 유용할까요?

bestdevel 2021. 1. 5. 21:17
반응형

클로저 : 왜 그렇게 유용할까요?


OO 개발자 로서 그 가치를 볼 수 있습니다. 어떤 부가 가치를 제공합니까? OO 세계에 가지고 있습니까?


클로저는 당신에게 추가적인 힘을주지합니다.

그들과 함께 달성 할 수있는 것은 무엇이든 그들 없이도 달성 할 수 있습니다.

그러나 코드를 더 명확하고 쉽게 만드는 데 매우 유용합니다. 그리고 우리 모두가 알다시피 깔끔하고 읽기 쉬운 짧은 코드는 디버그하기 약간가 약간 코드입니다.

가능한 사용에 대한 간단한 Java 예제를 제공합니다.

    button.addActionListener(new ActionListener() {
        @Override public void actionPerformed(ActionEvent e) {
            System.out.println("Pressed");
        }
    });

(Java에 클로저가있는 경우) 다음으로 대체됩니다.

button.addActionListener( { System.out.println("Pressed"); } );

클래스의 일반화로 볼 수 있습니다.

당신의 수업은 어떤 상태를 가지고 있습니다. 메소드가 사용할 수있는 멤버 변수가 있습니다.

클로저는 포함 된 함수에 로컬 상태에 대한 액세스를 제공하는 더 편리한 방법입니다.

함수에서 사용하려는 지역 변수에 대해 알고있는 클래스를 정의 할 수 있으며 현재 보이는 모든 변수에 암시 적으로 액세스 할 수 있습니다.

OOP 언어로 멤버 메소드를 정의 할 때 클로저는 "이 클래스에서 볼 수있는 모든 멤버"입니다.

"적절한"클로저를 지원하는 언어는 기본 화를 사용하여 함수의 클로저는 "여기에서 볼 수있는 모든 변수"입니다. " 여기서 "가 클래스 인 경우 기존 클래스 메소드가 있습니다.

" 여기 "다른 함수 안에가 있으면 함수형 프로그래머가 클로저로 생각하는 것이 있습니다. 이제 함수는 부모 함수에서 볼 수있는 모든 것에 액세스 할 수 있습니다.

따라서 "함수는 클래스 내에서만 정의 될 수있다"는 어리석은 제한을 제거하는 일반 화일뿐입니다. 그러나 "함수는 선언 된 지점에서 보이는 모든 변수를 볼 수 있습니다"라는 생각을 유지합니다.


저에게있어 클로저의 가장 큰 이점은 작업을 시작하고 작업을 실행할 때 어떤 일이 발생해야 할 것인지 지정하는 코드를 실행할 때입니다. 일반적으로 작업이 끝날 때 실행되는 코드는 처음에 사용할 수있는 데이터에 액세스해야하며 클로저를 사용하면 쉽게 수행 할 수 있습니다.

예를 들어 JavaScript의 일반적인 용도는 HTTP 요청을 시작하는 것입니다. 시작하는 사람은 아마도 응답이 도착했을 때 일어나는 일을 제어하고 싶을 것입니다. 따라서 다음과 같이 할 것입니다.

function sendRequest() {
  var requestID = "123";
  Ext.Ajax.request({
    url:'/myUrl'
    success: function(response) {
      alert("Request " + requestID + " returned");
    }
  });
}

JavaScript의 클로저로 인해 "requestID"는 성공 함수 내부에서 자동화됩니다. 요청 및 응답 함수를 작성하고 변수를 공유하는 방법을 보여줍니다. requestID를 인수로 전달하거나 requestID와 함수를 전달합니다.


이럴는 나중에 어느 시점에서 참조 할 코드 블록 컨텍스트 를 캡처 할 수 있고 필요할 때 / 만약 / 필요할 때 실행할 수 있다는 것입니다.

그들은 큰 문제가 될 것 같지 수 있으며 , 폐쇄 확실히 당신이 매일 일을 얻을 필요가 뭔가하지 않습니다 - 그들은하지만 쓰기에 코드를 훨씬 간단 코드와 청소기를 만들기 / 관리 할 수 있습니다.

[편집-위의 주석을 기반으로 한 코드 샘플]

자바 :

List<Integer> numbers = ...;
List<Integer> positives = new LinkedList<Integer>();
for (Integer number : integers) {
    if (number >= 0) {
        positives.add(number);
    }
}

Scala (유형 추론 및 와일드 카드와 같은 다른 장점 중 일부를 건너 뛰기 때문에 클로저의 효과 만 비교합니다) :

val numbers:List[Int] = ...
val positives:List[Int] = numbers.filter(i:Int => i >= 0)

유감입니다. 사람들은 더 이상 에듀에서 스몰 토크를 배우지 거기에서 클로저는 제어 구조, 일련의 열거, 예외 처리가 사용됩니다. 좋은 예를 들어, 다음은 반복 작업 처리기입니다 (Smalltalk).

|actionQueue|

actionQueue := SharedQueue new.
[
    [
        |a|

        a := actionQueue next.
        a value.
    ] loop
] fork.

actionQueue add: [ Stdout show: 1000 factorial ].

그리고 Smalltalk를 읽을 수있는 사람들을 위해 JavaScript 구문에서 동일합니다.

var actionQueue;

actionQueue = new SharedQueue;
function () {
    for (;;) {
        var a;

        a = actionQueue.next();
        a();
    };
}.fork();

actionQueue.add( function () { Stdout.show( 1000.factorial()); });

(보시다시피 구문은 코드를 읽는 데 도움이됩니다.)

편집 : 블록 내부에서 actionQueue가 참조되는 방식을 확인하십시오. 이는 분기 된 것 블록 작동합니다. 이것이 클로저를 사용하기 쉽게 만드는 이유입니다.


다음은 몇 가지 흥미로운 기사입니다.


클로저는 OO 세계에 아주 잘 맞습니다.

예를 들어 C # 3.0을 고려하십시오. 클로저 및 기타 많은 기능적 측면이 있지만 여전히 매우 객체 지향 언어입니다.

내 경험상 C #의 기능적 측면은 클래스 멤버의 구현 내에 머무르는 경향이 있으며, 내 개체가 노출되는 공용 API의 일부가 아닙니다.

따라서 클로저의 사용은 객체 지향 코드에서 구현 세부 사항이되는 경향이 있습니다.

단위 테스트 중 하나 ( Moq 에 대한 ) 의이 코드 스 니펫이 보여 주듯이 항상 사용합니다 .

var typeName = configuration.GetType().AssemblyQualifiedName;

var activationServiceMock = new Mock<ActivationService>();
activationServiceMock.Setup(s => s.CreateInstance<SerializableConfigurationSection>(typeName)).Returns(configuration).Verifiable();

C #의 클로저 기능이 아니었다면 입력 값 (typeName)을 Mock 기대의 일부로 지정하는 것이 매우 어려웠을 것입니다.


결론 쿼리 : "(폐쇄)가 OO 세계에 적합합니까?"

많은 언어에서 클로저는 일류 함수와 함께 OO 프로그램을 고안하기위한 기초를 제공합니다 : Javascript, Lua 및 Perl이 떠 오릅니다.

내가 익숙한 또 다른 "전통적인"OO 언어 인 Java에는 두 가지 주요 차이점이 있습니다.

  1. 함수는 일류 구조 아닙니다.
  2. Java에서 OO의 구현 세부 사항 (클로저가 내부적으로 사용되는지 여부)은 Javascript, Lua 및 Perl 에서처럼 개발자에게 직접 노출되지 않습니다.

따라서 Java와 같은 "전통적인 OO"언어에서 클로저 추가는 대체로 구문상의 설탕에 불과합니다.


컴파일 된 프로그래밍의 세계에서 클로저의 이점이 눈에 띄지 않을 수도 있습니다. JavaScript에서 클로저는 엄청나게 강력합니다. 그 이유는 두 가지입니다.

1) JavaScript는 해석 된 언어이므로 명령 효율성과 네임 스페이스 보존은 많은 양의 입력을 평가하는 대규모 프로그램이나 프로그램에서보다 빠르고 응답 성이 뛰어난 실행을 위해 매우 중요합니다.

2) JavaScript는 람다 언어입니다. 즉, JavaScript 함수에서 범위를 정의하는 첫 번째 클래스 개체이며 부모 함수에서 자식 개체에 액세스 할 수 있습니다. 변수는 부모 함수에서 선언되고 자식 함수에서 사용되며 자식 함수가 반환 된 후에도 값을 유지할 수 있기 때문에 중요합니다. 즉, 해당 함수의 마지막 반복에서 이미 정의 된 값으로 함수에서 변수를 여러 번 재사용 할 수 있습니다.

결과적으로 클로저는 엄청나게 강력하고 JavaScript에서 뛰어난 효율성을 제공합니다.


위의 예를 보면 비트를 추가 할 수 있습니다.

  • 스타일, 상태를 숨기는 부분, 표현의 연결을 고맙게 생각하지만 이것으로는 충분하지 않습니다

  • 간단하고 명시적인 코드에 대해 많은 것을 말할 수 있습니다.

  • Scala, Perl 및 기타 Scheme 유형 언어는 언어 디자이너의 특정 사고 방식에 대한 일종의 속기 또는 "더 생산적"으로 만들도록 설계되었다고 생각합니다.

나는 단순성과 명시 성의 더 나은 방법으로 파이썬의 단순성과 자바 등의 초기 구문을 취할 것입니다.

좁은 공간에서 암호 체인 클로저를 작성하는 것은 매우 빠를 수 있습니다. 그러나 모든 것은 단순한 객체와 알고리즘으로 수행 될 수 있습니다.

폐쇄가 필요하지만 일류 시민임을 보증하기 위해 자주는 아닙니다.

참조 URL : https://stackoverflow.com/questions/1305570/closures-why-are-they-so-useful

반응형