인터페이스와 추상클래스와 익명(무명)클래스

Updated:

Abstract class VS interface

우선 interface를 살펴보자

Interface

껍데기,설계도, 어떤 틀에 대한 명세

  • 모든 메소드가 추상메소드
  • 그 의미는 interface를 구현(이행)한 클래스는 강제적으로 interface의 모든 메소드를 강제적으로 구현(이행)해야함
  • 즉, 필요없는 메소드도 구현(이행)해야하는 짜증을 유발할수는 있음

그럼 언제쓰냐

협업을하거나, 큰 프로젝트의 경우 유용하게 쓸수있다.

왜냐하면, 어떤 사람이 무슨 일을 하는지 몰라도, 약속을 정해놓으면, 즉 설계도를 짜놓으면, 각 사람들은 그 설계도에 맞게, 본인의 일을 열심히 하면 되기때문임

즉, 협업과 생산성을 높일수 있다라는 것이다

Abstract class

말 그대로 추상 클래스이다.

해당하는 클래스를 정확하게 정의 하지 못할때 추상클래스를 사용할수 있다.

예를 들면, 동물 클래스를 들수 있다.

동물의 경우, 동물의 특성을 전부 합친다면, 엄밀히 어떤 동물을 가리키는지 알수없다.

그래서 추상클래스는 ?라고 보면된다.

추상클래스가 인터페이스와 다른점이자 장점? 이라함이면

일반적인 클래스처럼 쓸수 있다는 것이다. 단 인스턴스화가 안될뿐

하지만 익명클래스를 이용해서 마치 인스턴스화 된것처럼 흉내를 낼수있다.
그러나 인터페이스나 추상 클래스가 인스턴스가 된것은 아니다. 내부적으로 익명클래스가 인터페이스나 추상 클래스로부터 상속을 받아서 만들어진 형태(인스턴스)가 익명클래스‘이기 때문이다

(이건 제 생각이므로, 자세히 알고계신분은 댓글 남겨주시면 정말 감사하겠습니다)


익명 클래스

  • 말 그대로 이름이 없는 클래스

그러나 의미를 명확히 생각을 해봐야함!!

익명 클래스는 엄밀히 말해서 상속을 받는 클래스인데, 이름이 없을뿐인 클래스이다.

왜냐하면, 익명 클래스의 구조를 보면, 메소드를 Override를 받기 때문

그럼 익명클래스를 왜 쓰냐?

  • 상속 받은 클래스가 상당히 많아질 경우에 유용하다
  • 왜냐하면, 매번 상속 받은 클래스를 만든다는거 자체가 메모리에 상당히 부담이됨
  • 그래서 상속 받은 클래스를 재사용 하는 측면에서 상당히 유리
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        A a = new A() {
            int a;

            @Override
            public void testAnomy(String s) {
                System.out.println("toUpperCase: " + s.toUpperCase());
            }

            @Override
            public void setGood(int a) {
                this.a = a;
                this.a += 10;
                getA();
            }

            public void getA() {
                System.out.println("a의 결과는?" + this.a);
            }
        };
        List<Integer>v=null;
        v.add(1);
        A b = new ok() {
            @Override
            public void setGood(int a) {
                // super는 말그대로 부모를 가리킨다.
                // 그럼 단순히 super만 하면, 어떻게 메소드를 가리켜서 실행시키게 할수있나?
                // 아 super();가 이미 눈에 보이지 않지만, 자동적으로 생성이 된다.
                // 그래서, super.메소드()이런식으로 접근이 가능한것이다.
                // 여기서 부모의 생성자가 명시되어있지 않은 경우
                super.setGood(a+213);
            }
        };
        b.setGood(10);
        for (int i = 0; i < 10; i++) {
            a.testAnomy("good");
            a.setGood(i);
        }
    }

    private static void test(A a) {
        System.out.println(a);
    }

    private interface A {
        void testAnomy(String s);

        default void setGood(int a) {
            System.out.println(a);
        }
    }
    private static abstract class AB implements A{

        @Override
        public void testAnomy(String s) {
            System.out.println("LowerCase : "+s.toLowerCase());
        }

        @Override
        public void setGood(int a) {
            System.out.println("AB result: "+a);
        }
    }
    private static class ok extends AB{
        @Override
        public void setGood(int a) {
            a+= 100023;
            super.setGood(a);
        }
    }

보다시피, A가 인터페이스인데, 그 인터페이스를 상속한 익명클래스가 생성이 되었다!

근데 중요한건, 저기서 getA() 메소드의 경우를 보자

저거는 상속을 받은 메소드가 아니다. 직접 추가적으로 만들어졌을뿐

그래서 a라는 익명클래스에서 직접적으로 접근이 안된다.

왜냐하면, 형태가 a 인터페이스 형태이기 때문이다!!

그리고, super는 바로 상속하는 윗부모를 가리킨다.

그러면 내가 super에 생성자를 준것도 아닌데, 왜 접근이 가능할까?

자바 컴파일러가 자동적으로 기본 생성자를 만들어주기때문이다

Leave a comment