추상 클래스와 인터페이스

jaegeunsong97·2023년 1월 14일
0
post-thumbnail

2023_1_14_TIL

추상클래스의 정의

  • 추상 메소드 -> 메서드의 본체가 완성되지 않은 미완성 메서드
    • 추상 메소드 1개 이상 포함하고 있는 클래스는 반드시 추상 클래스
  • 메소드 완성의 기준
abstract class A {
	abstract void abc();// 미완성 메소드
}
class B extends A {
	void abc() {// 중괄호 안에 아무런 코드가 없어도 완성된 메소드
    }
}

추상 클래스의 특징

  • 추상 클래스는 내부의 미완성 메소드 있음 -> 객체 직접 생성X
  • 힙 메모리에 내부 요소가 미완성인 채로 못들어감
  • 추상 클래스를 상속한 자식 클래스를 생성 -> 그 자식 클래스로 객체 생성 가능
  • 추상 클래스 상속하는 자식 클래스는 부모에게 상속받은 미완성 메서드(추상 메서드) 반드시 완성(오버라이딩)
  • 추상 클래스 안에는 반드시 추상 메소드만 있어야함? -> No

추상 클래스 타입의 객체 생성 방법

  • 추상 클래스를 상속한 일반 클래스를 생성
    • 장점 -> 객체 깔끔하고 여러개 생성 가능
    • 단점 -> 추가 클래스 생성
abstract class A {
    abstract void abc();
}
class B extends A {
    void abc() {
        System.out.println("방법 1. 자식 클래스 생성 및 추상 클래스 구현");
    }
}
public class AbstractClass_1 {
    public static void main(String[] args) {
        A b1 = new B();
        A b2 = new B();

        b1.abc();
        b2.abc();
    }
}
  • 익명 이너 클래스 사용
    • 장점 -> 추가 클래스 만들 필요 없음
    • 단점 -> 객체 생성할 떄마다 계속 같은 거 반복
abstract class A {
    abstract void abc();
}

public class AbstractClass_2 {
    public static void main(String[] args) {
        A a1 = new A() {
            void abc() {
                System.out.println("방법 2. 익명 이너 클래스 방법으로 객체 생성");
            }
        };
        A a2 = new A() {
            void abc() {
                System.out.println("방법 2. 익명 이너 클래스 방법으로 객체 생성");
            }
        };
        a1.abc();
        a2.abc();
    }
}

인터페이스의 정의와 특징

  • 인터페이스 내부 모든 필드 -> public static final
  • 인터페이스 내부 모든 메소드 -> public abstract
  • 예외
    • default method
    • static method
    • private method
interface A {
    public static final int a = 3;
    public abstract void abc();
}
interface B {
    int b = 3;
    void bcd();
}

인터페이스의 상속

  • 다중 상속 가능
    • 클래스는 다중 상속 불가능 -> 메소드, 필드의 충돌이 있기때문에
    • 하지만 인터페이스는 가능 -> 모든 필드가 public static final -> 안 겹침
  • 인터페이스는 모든 필드와 메소드가 public으로 되어있음 -> 모든 자식 클래스 구현 메소드 public만 가능

인터페이스 타입의 객체 생성 방법

  • 추상 클래스와 동일
  • 자식 클래스를 직접 정의해 인터페이스 객체 생성
interface A {
    int a = 3;
    void abc();
}
class B implements A {
    public void abc() {
        System.out.println("방법 1. 자식 클래스 생성자로 객체 생성");
    }
}
public class CreateObjectOfInterface_1 {
    public static void main(String[] args) {
        A b1 = new B();
        A b2 = new B();
        b1.abc();
        b2.abc();
    }
}
  • 익명 이너 클래스를 활용한 인터페이스 객체 생성
interface A {
    int a = 3;
    void abc();
}
public class CreateObjectOfInterface_2 {
    public static void main(String[] args) {
        A a1 = new A() {
            public void abc() {
                System.out.println("방법 2. 익명 이너 클래스를 이용한 객체 생성");
            }
        };
        A a2 = new A() {
            public void abc() {
                System.out.println("방법 2. 익명 이너 클래스를 이용한 객체 생성");
            }
        };
        a1.abc();
        a2.abc();
    }
}

인터페이스의 필요성

  • 오류를 잡을 수 있음

디폴트 매소드와 정적 메소드

  • 디폴트 메소드 -> 인터페이스 내부에 완성된 메소드 삽입
    • 자식 클래스가 무조건 오버라이딩 할 필요 없음(하고 싶으면 해도 됨)
interface A {
    void abc();
    default void bcd() {
        System.out.println("A 인터페이스의 bcd()");
    }
}
class B implements A {
    public void abc() {
        System.out.println("B 클래스의 abc()");
    }
}
class C implements A {
    public void abc() {
        System.out.println("C 클래스의 abc()");
    }
    public void bcd() {
        System.out.println("C 클래스의 bcd()");
    }
}
public class DefaultMethod_1 {
    public static void main(String[] args) {
        A a1 = new B();
        A a2 = new C();
        a1.abc();
        a1.bcd();
        a2.abc();
        a2.bcd();
    }
}
  • 부모 인터페이스 디폴트 메소드 호출하는 방법 -> 인터페이스명.super.디폴트메소드
    • 이렇게 하는 이유 -> 인터페이스는 다중상속이여서, 누가 부모님인지 모르거든
    • 만약 super.디폴트메소드 -> 클래스는 Object를 상속하지? 네! -> 그럼 Object에서 있지도 않은 디폴트 메소드를 찾는 거(삽질)
interface A {
    default void abc() {
        System.out.println("A 인터페이스의 abc()");
    }
}
class B implements A {
    public void abc() {
        A.super.abc();// 요기입니다요 요기  <<<<<<-------
        System.out.println("B 클래스의 abc()");
    }
}
public class DefaultMethod_2 {
    public static void main(String[] args) {
        B b = new B();
        b.abc();
    }
}
  • 정적 메소드
interface A {
    static void abc() {
        System.out.println("A 인터페이스의 정적 메소드 abc()");
    }
}
public class StaticMethod {
    public static void main(String[] args) {
        A.abc();
    }
}

참조

https://velog.io/@garam87/%EC%B6%94%EC%83%81%ED%81%B4%EB%9E%98%EC%8A%A4abstract-class

profile
현재 블로그 : https://jasonsong97.tistory.com/

0개의 댓글