반응형

This might be simple for seasoned java developers but I just cant seem to figure it out. I read a post from here. The code was

View v = new View(this) {
    @Override
    protected void onDraw(Canvas canvas) {
        System.out.println("large view on draw called");
        super.onDraw(canvas);
    }
};

It was an Android question. Here the user creates an instance of a view and overrides a method in a single line. Is there a name for this kind of coding?

My second doubt is, he overrides a protected method from another package. Isn't protected mean package private. I know this will work as I tried it out but I just couldn't figure out why it worked. So why is this code working?

I did try to google this and search in SO before asking but couldn't figure out an answer.

 

 

 

=>

That is not exactly a kind of coding. That is a Java anonymous class. It is very common in Android and in general with event listeners and that kind of stuff.

For more details you can read this link (probably not the best one):

The anonymous inner classes is very useful in some situation. For example consider a situation where you need to create the instance of an object without creating subclass of a class and also performing additional tasks such as method overloading.

About your second question, the keyword protected means that the method is only available to subclasses, so it is possible to override the method.

 


 

 

 

 

package com.jjjjj.myevent;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    TextView textView;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.textView);
        View view = findViewById(R.id.view);
        view.setOnTouchListener(new View.OnTouchListener(){

            @Override
            public boolean onTouch(View var1, MotionEvent event)
            {
                int action = event.getAction();

                float curX = event.getX();
                float curY = event.getY();

                if(action ==  MotionEvent.ACTION_DOWN )
                {
                    println("손가락 눌림 : " + curX + ", " + curY);
                }
                else if(action ==  MotionEvent.ACTION_MOVE )
                {
                    println("손가락 움직임 : " + curX + ", " + curY);
                }
                else if(action ==  MotionEvent.ACTION_UP )
                {
                    println("손가락 뗌 : " + curX + ", " + curY);
                }
                return true;
            }

        });
    }


    public void println(String data)
    {
        textView.append(data + "\n");
    }
}

 

가장 상단 푸른색을 눌렀다가 움직이고 때면 하단의 글자 처럼 마우스에 대한 입력들을 볼 수가 있습니다

 

 

 

 


 

익명객체(익명클래스) 란?

이번시간에는 자바 익명객체(익명클래스)에 대해서 알아보도록 하겠습니다.

익명객체(익명클래스) 말그대로.. 이름이 없는 객체? 클래스?,,,그래서 무명클래스라고도 합니다.

언어의 사전적인 의미는 파악이 되셨을거라 생각됩니다.

그럼 도대체 이름도 없고 뭔가 근본도 없는것 같은 이 익명객체(익명클래스)를 왜 사용해야하는지.. 바로 설명들어가겠습니다.

 

 

익명객체(익명클래스) 를 사용하는 이유!!

이름 부터 눈치 채셨겠지만, 이름이 없다는 것은 별로 기억되지 않아도 된다는 거겠죠..

나중에 다시 불러질 이유가 없다는 뜻입니다. 이 말을 좀 더 있어보이게 말하면...

프로그램에서 일시적으로 한번만 사용되고 버려지는 객체입니다. 좀 더 풀어서 생각해보면 일시적으로 사용된다는 것은 나중에 재사용이 되지 않는다는 것이며, 재사용이 될 필요가 없다는 뜻은 확장성이 그렇게 좋지 못하다는 뜻입니다.

자바에서 확장성을 고려해서 코딩을하고 설계를 하는 것도 중요합니다. 정말 중요하죠.. 하지만, 최소한의 확장성이 성립되려면 어느정도 유지보수에 대한 이점이 있어야 하는데, 오히려 확장성을 고려해서 설계를 했다간 유지보수에서 더 불리한 경우가 있습니다(아래 예시 참고). 자,,,익명클래스를 사용해야하는 이유를 정리하자면....


1. 프로그램 내에서 일시적으로(단발성으로) 한번만 사용되어야 하는 객체일 경우
   -> UI 이벤트처리, 스레드 객체 등 (단발성 이벤트 처리)

2. 재사용성이 없고, 확장성을 활용하는 것이 유지보수에서 더 불리할 때

  -> 비즈니스 로직이 정말 재각각이며, 재사용성이 전혀없어 매번 클래스를 생성해야하는 비용이 더 많을때

 

 

 

익명객체(익명클래스) 구현하는 방법 (익명 자식객체 생성, 익명 구현객체 생성)

 

익명객체(클래스)를 구현하는 방법은 크게 2가지 입니다.

부모/자식간 상속아래 익명 자식객체를 생성할 것인가?

아니면, 인터페이스를 구현한 익명 구현객체를 생성할 것인가? (다음 시간에 다루겠음)

이번시간에는 명 자식객체에 대해서 알아보겠습니다.

 

익명 자식객체 생성 방법에는 아래 3가지방법으로 구현할 수 있습니다.
1. 필드의 초기값
2. 로컬변수의 초기값
3. 매개변수의 매개값

 

정의는 아래와 같이 하면 됩니다. (세미콜론 ; 으로 마무리)

 

부모클래스 [필드|변수] = new 부모클래스(매개값, ... ) {

 

};

 

자 그럼 코드를 보면서 설명하도록 하겠습니다.

package Anonymous;

public class Insect {

	void attack(){
		System.out.println("곤충은 공격을 한다");
	}
}

우선 곤충 Insect 이라는 부모클래스를 정의했습니다.

향후 Insect 부모 클래스는 일시적으로 정의된 익명객체를 담아둘 변수로 사용되기도 하고, 익명객체가 무엇을 재정의해야할지 어느정도 컨셉을 잡아주는 역할로 사용됩니다.(상속개념)

package Anonymous;

public class Anonymous {

	//★★방법 1 : 필드에 익명자식 객체를 생성 
	Insect spider1 = new Insect(){
		
		String name = "무당거미";
		//거미줄을 치다.
		void cobweb(){
			System.out.println("사각형으로 거미줄을 친다.");
		}
		
		@Override
		void attack() {
			System.out.println(name + " 독을 발사한다.");
		}
	};
	
	//★★방법2 : 로컬변수의 초기값으로 대입
	void method1(){
		Insect spider2 = new Insect(){
			
			String name = "늑대거미";
			//거미줄을 치다.
			void cobweb(){
				System.out.println("육각형으로 거미줄을 친다.");
			}
			
			@Override
			void attack() {
				System.out.println(name + " 앞니로 문다.");
			}
		};
		
		//로컬변수이기 때문에 메서드에서 바로 사용
		spider2.attack();
	}
	
	//★★방법3 : 익명객체 매개변수로 대입
	void method2(Insect spider){
		spider.attack();
	}
	
	
}

그다음, 부모(곤충)객체 필드에 자식 익명객체를 바로 정의하여 초기값을 할당하고 있습니다.

또, method1을 보시면 해당 메서드 내부에서 지역적으로 익명객체를 생성하고, 바로 spider2.attack() 메서드를 호출하여 익명객체를 사용했습니다.

 

마지막으로 부모(곤충)객체를 매개변수 인자로 받게끔 하고, 받은 후 바로 spider.attack() 메서드를 호출하여 사용하도록 했습니다. 이제 위에서 정의한 Anonymous 클래스를 아래 main 함수에서 호출하도록 하면 아래와 같이 결과값이 나옵니다.

 

 

 

 

 

참고로!! 익명자식객체에서 새롭게 정의된 필드와 메소드는 자식객체 레벨에서만 사용되기 때문에 외부에서는 사용할 수 없습니다! 생각해보면 익명객체를 받아준 변수는 부모타입의 클래스이기 때문에 부모레벨에서 정의된 필드나 메서드만 사용이 가능합니다.

그래서 a.spider1.name, a.spider1.cobweb() 은 사용할 수 없고

a.spider1.attack() 메서드는 사용할 수 있는 것입니다.

package Anonymous;

public class AnonymousExample {

	public static void main(String[] args) {
		
		Anonymous a = new Anonymous();
		
		//방법 1 : 익명객체 필드 사용
		a.spider1.attack();

		//방법2 : 익명객체 로컬 변수 사용
		a.method1();
		
		//방법3 : 매개변수로 익명개체 사용
		a.method2(new Insect(){
			String name = "타란툴라";
			
			//거미줄을 치다.
			void cobweb(){
				System.out.println("그냥 마구잡이로 친다.");
			}
			
			@Override
			void attack() {
				System.out.println(name + " 공격 안하고 후퇴한다..");
			};
		});
		
		//익명객체 내부에서 새롭게 정의된 필드,메서드는 부모객체로 생성된 spider1에서 접근할 수 없음!!!
		a.spider1.name = "왕거미"; //익명객체에서 새롭게 정의된 필드 (접근불가)
		a.spider1.cobweb(); //익명객체에서 새롭게 정의된 메서드 (접근불가)
		a.spider1.attack(); //부모클래스 Insect에서 오버라이딩해서 재정의한 메서드 (접근가능)
	}

}

결과

무당거미 독을 발사한다.
늑대거미 앞니로 문다.
타란툴라 공격 안하고 후퇴한다..

 

 

 

ref : https://stackoverflow.com/questions/7347612/java-overriding-methods-when-creating-new-instance-of-a-class

ref : https://limkydev.tistory.com/226

반응형

'App' 카테고리의 다른 글

android : AsyncTask  (0) 2022.10.27
android Handler 로 스레드 실행 post  (0) 2022.10.27
Android : Activity  (0) 2022.10.19
(View,ViewGroup) 안드로이드 View와 ViewGroup  (0) 2022.10.12

+ Recent posts