programing

익명 클래스에 매개 변수를 전달하려면 어떻게 해야 합니까?

prostudy 2022. 6. 7. 21:28
반응형

익명 클래스에 매개 변수를 전달하려면 어떻게 해야 합니까?

파라미터를 전달하거나 익명의 클래스에 외부 파라미터에 액세스할 수 있습니까?예를 들어 다음과 같습니다.

int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // How would one access myVariable here?
    }
});

리스너를 실제 이름 있는 클래스로 만들지 않고 리스너가 myVariable에 액세스하거나 myVariable을 전달할 수 있는 방법이 있습니까?

네, 'this'를 반환하는 이니셜라이저 메서드를 추가하고 즉시 해당 메서드를 호출합니다.

int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    private int anonVar;
    public void actionPerformed(ActionEvent e) {
        // How would one access myVariable here?
        // It's now here:
        System.out.println("Initialized with value: " + anonVar);
    }
    private ActionListener init(int var){
        anonVar = var;
        return this;
    }
}.init(myVariable)  );

'최종' 선언은 필요 없습니다.

엄밀히 말하면, 익명의 수업에는 컨스트럭터가 있을 수 없기 때문입니다.

그러나 클래스는 범위를 포함하는 변수를 참조할 수 있습니다.어나니머스 클래스의 경우 포함된 클래스의 인스턴스 변수 또는 최종으로 표시된 로컬 변수일 수 있습니다.

edit: Peter가 지적한 바와 같이 익명 클래스의 슈퍼 클래스 작성자에게 파라미터를 전달할 수도 있습니다.

네. 내부 클래스에서 볼 수 있는 변수를 캡처할 수 있습니다.유일한 제한은 그것이 최종이어야 한다는 것이다.

다음과 같이 합니다.

final int myVariable = 1;

myButton.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        // Now you can access it alright.
    }
});

이거면 마법이 될 거야

int myVariable = 1;

myButton.addActionListener(new ActionListener() {

    int myVariable;

    public void actionPerformed(ActionEvent e) {
        // myVariable ...
    }

    public ActionListener setParams(int myVariable) {

        this.myVariable = myVariable;

        return this;
    }
}.setParams(myVariable));

http://www.coderanch.com/t/567294/java/java/declare-constructor-anonymous-class 에 나타나듯이 인스턴스 이니셜라이저를 추가할 수 있습니다.이름이 없고 (컨스트럭터처럼) 먼저 실행되는 블록입니다.

Java 인스턴스 이니셜라이저에서도 논의되는 것 같습니다.인스턴스 이니셜라이저는 컨스트럭터와 어떻게 다른가요?그럼 컨스트럭터와의 차이점에 대해 설명합니다.

이 솔루션은 구현된 익명 클래스를 반환하는 메서드를 사용하는 것입니다.정규 인수는 메서드에 전달될 수 있으며 익명 클래스 내에서 사용할 수 있습니다.

예: (일부 GWT 코드에서 텍스트 상자 변경을 처리합니다.)

/* Regular method. Returns the required interface/abstract/class
   Arguments are defined as final */
private ChangeHandler newNameChangeHandler(final String axisId, final Logger logger) {

    // Return a new anonymous class
    return new ChangeHandler() {
        public void onChange(ChangeEvent event) {
            // Access method scope variables           
            logger.fine(axisId)
        }
     };
}

이 예에서는 새로운 어나니머스 class-method가 다음과 같이 참조됩니다.

textBox.addChangeHandler(newNameChangeHandler(myAxisName, myLogger))

또는 OP의 요건을 사용하여 다음을 수행합니다.

private ActionListener newActionListener(final int aVariable) {
    return new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            System.out.println("Your variable is: " + aVariable);
        }
    };
}
...
int myVariable = 1;
newActionListener(myVariable);

다른 사람들은 이미 익명 클래스가 최종 변수에만 액세스할 수 있다고 대답했습니다.그러나 그들은 원래의 변수를 어떻게 최종값이 아닌 상태로 유지할 것인가 하는 문제를 열어두고 있다.Adam Mlodzinski는 해결책을 제시했지만 꽤 비대하다.이 문제에 대한 훨씬 더 간단한 해결책이 있습니다.

당신이 원하지 않는다면myVariable최종적으로는 새로운 범위로 묶어야 합니다.최종인지 아닌지는 중요하지 않습니다.

int myVariable = 1;

{
    final int anonVar = myVariable;

    myButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            // How would one access myVariable here?
            // Use anonVar instead of myVariable
        }
    });
}

Adam Mlodzinski는 그의 대답에서 다른 어떤 것도 하지 않고 훨씬 더 많은 코드를 가지고 있다.

플레인 람다("lambda 식은 변수를 캡처할 수 있습니다")를 사용할 수 있습니다.

int myVariable = 1;
ActionListener al = ae->System.out.println(myVariable);
myButton.addActionListener( al );

또는 기능까지

Function<Integer,ActionListener> printInt = 
    intvar -> ae -> System.out.println(intvar);

int myVariable = 1;
myButton.addActionListener( printInt.apply(myVariable) );

함수를 사용하면 데코레이터와 어댑터를 리팩터링할 수 있습니다.여기를 참조해 주십시오.

람다에 대해 배우기 시작한 지 얼마 안 됐으니, 혹시라도 실수를 발견하면 댓글을 달아주세요.

외부 변수에 값을 넣는 간단한 방법(익명 클래스에 속하지 않음)은 다음과 같습니다.

마찬가지로 외부 변수 값을 가져오려면 원하는 값을 반환하는 메서드를 만들 수 있습니다.

public class Example{

    private TypeParameter parameter;

    private void setMethod(TypeParameter parameter){

        this.parameter = parameter;

    }

    //...
    //into the anonymus class
    new AnonymusClass(){

        final TypeParameter parameterFinal = something;
        //you can call setMethod(TypeParameter parameter) here and pass the
        //parameterFinal
        setMethod(parameterFinal); 

        //now the variable out the class anonymus has the value of
        //of parameterFinal

    });

 }

"myVariable"이 필드인 경우 다음과 같이 수식할 수 있습니다.

public class Foo {
    int myVariable = 1;

    new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            Foo.this.myVariable = 8;
        }
    });
}

익명의 수업은 기본적으로 람다와 같다고 생각했는데 더 나쁜 구문으로는...이는 사실이지만 구문은 더욱 악화되어 로컬 변수가 포함된 클래스로 블리딩됩니다.

부모 클래스의 필드로 만들어 최종 변수에 액세스할 수 없습니다.

인터페이스:

public interface TextProcessor
{
    public String Process(String text);
}

클래스:

private String _key;

public String toJson()
{
    TextProcessor textProcessor = new TextProcessor() {
        @Override
        public String Process(String text)
        {
            return _key + ":" + text;
        }
    };

    JSONTypeProcessor typeProcessor = new JSONTypeProcessor(textProcessor);

    foreach(String key : keys)
    {
        _key = key;

        typeProcessor.doStuffThatUsesLambda();
    }

Java 8(EE world에 갇혀 있고 아직 8이 되지 않음)에서 이 문제를 해결했는지 모르겠지만 C#에서는 다음과 같습니다.

    public string ToJson()
    {
        string key = null;
        var typeProcessor = new JSONTypeProcessor(text => key + ":" + text);

        foreach (var theKey in keys)
        {
            key = theKey;

            typeProcessor.doStuffThatUsesLambda();
        }
    }

c#에는 별도의 인터페이스가 필요 없습니다.그립다!자바에서 더 나쁜 디자인을 만들고 더 많은 것을 반복하고 있습니다. 왜냐하면 어떤 것을 재사용하기 위해 자바에서 추가해야 하는 코드와 복잡성의 양은 복사하여 붙여넣는 것보다 더 나쁘기 때문입니다.

언급URL : https://stackoverflow.com/questions/5107158/how-to-pass-parameters-to-anonymous-class

반응형