JAVA/자바 완전 정복

추상클래스와 인터페이스

GaeGim 2022. 7. 2. 23:46
반응형

추상 메서드 : 메서드의 본체가 완성되지 않은 미완성 메서드

중괄호 안이 비어 있는 게 아니라 아예 존재하지 않은 메서드이기 때문에 명령어가 끝남을 알리는 세미콜론으로 끝나야 한다.

 

문법)

abstract 리턴타입 메서드명(입력매개변수);

 

· 추상 클래스는 추상 메서드(미완성 메서드)를 하나라도 포함하고 있으면 추상 클래스임을 명시를 해줘야 한다.

하지만 추상클래스 안에 추상 메서드가 꼭 있어야 하는 것은 아니다. 그저 하나라도 존재하면 명시해 줘야 한다는 것이다.

 

 문법)

abstract class 클래스명{}

 

 

※ 메서드 완성 기준 : 중괄호의 존재 여부.

중괄호가 있고 그 안에 내용은 아무 것도 없어도 완성 메서드로 취급된다.

내용이 아무 것도 없는 완성 메서드는 아무 일도 하지 않는 작동을 한다.

 

 

추상 클래스는 내부 미완성 메서드때문에 객체를 직접 생성할 수 없다.

객체를 힙 메모리에 넣으려면 초기화가 되어야 하는데 미완성 메서드는 당연히 힙 메모리에 포함될 수 없는 것이다.

 

따라서 추상 클래스를 상속 받는 자식 클래스로 객체를 생성할 수 있다.

추상 클래스를 상속받은 자식 클래스 객체 내부엔 부모 클래스인 추상클래스 메서드가 구현되어 있어야 할 것이다. 구현하는 방법은 추상 클래스의 메서드를 오버라이딩해서 완성시키면 된다. 그렇게 객체를 만들면 다형적 표현으로 부모 추상 클래스 타입으로 선언할 수도 있다.

 

※ 미완성 메서드든 완성 메서드든 부모에게 메서드를 상속받은 자식 클래스에서 메서드를 재정하는 것을 통칭해 오버라이드라고 하고 미완성 메서드를 자식 클래스에서 완성시키는 것을 구현한다고 한다.

 

 

· 추상 클래스 객체를 만드는 또다른 방법은 익명 이너 클래스를 사용하는 것이다. 

이는 컴파일러가 추상 클래스를 상속해 메서드 오버라이딩을 수행한 클래스를 생성하고 그 클래스로 객체를 생성하는 것이다. 이때 내부적으로 생성된 클래스명은 알 수가 없어 익명 이너 클래스라고 부르는 것이다.

 

문법)

클래스명 참조변수명 = new 생성자() { 추상 메서드의 메서드 오버라이딩 };

 

 

· 두 객체 생성 방법의 장단점

자식 클래스로 객체 생성 방법은 한 번 정의하면 자식 클래스의 생성자 호출만으로도 객체를 몇 개든 만들 수 있어 객체를 여러 번 만들어야 할 때 쓰면 용이할 것이다.

익명 이너 클래스는 추가적인 자식 클래스 정의가 불필요하다. 따라서 한 번만 객체를 사용할 때 용이하겠지만 클래스명을 알 수 없기 때문에 객체를 정의할 때마다 익명 이너 클래스를 정의해야 한다(추상 메서드 구현 필요).

 

 

 

 

  • 인터페이스

의미 : 입출력 방식의 호환성

 

인터페이스 내부 모든 필드는 public static final로 정의되고

static과 default 메서드 이외 모든 메서드는 public abstract으로 정의된다.

class 대신 interface 키워드를 사용한다.

interface 인터페이스명 {
    public static final 자료형 필드명 = 값;
    puvlic abstract 리턴타입 메서드명();
}

 

인터페이스 내 필드와 메서드의 제어자가 확정되어 있기 때문에 제어자를 빼먹어도 컴파일러가 자동으로 각각의 제어자를 추가시켜준다. 필드는 static 제어자가 있기 때문에 갹체 생성없이 인터페이스명으로 바로 접근이 가능하다.

 

 

· 인터페이스 상속

클래스 상속과 달리 쉼표(,)를 이용해 다중 상속이 가능하다.같은 타입을 상속받을 땐 extends 키워드를, 다른 키워드를 상속받을 땐 implements를 사용※ 인터페이스는 클래스를 상속받을 수 없다(이미 완성된 것을 미완성된 것으로 상속시키기는 불가능).

//클래스에서 인터페이스를 상속하는 구조
클래스명 implements 인터페이스명, ... , 인터페이스명 {  //내용  }

//클래스와 인터페이스 동시에 상속하는 구조
클래스명 extends 클래스명 implements 인터페이스명, ..., 인터페이스명 { //내용 }
//extends와 implements의 순서는 바뀔 수 없다

 

클래스 다중 상속이 안된 이유는 두 부모의 필드나 메서드명이 같을 경우 구분하지 못해서였다.

하지만 인터페이스는 모든 필드가 public static final로 정의되어 있어 실제 데이터 값은 각각의 인터페이스 내부에 존재하기 때문에 공간이 겹치지 않기 때문이다. 메서드 또한 모두 미완성인 상태라 힙 메모리에 존재하지 않기도 하고 자식 클래스에서 구현되기 때문에 문제가 되지 않는다.

 

 

· 일반 클래스가 인터페이스를 상속받을 때 주의해야 할 점이 몇가지 있는데, 그 중 하나가 일반 클래스는 인터페이스의 추상 메서드를 구현(중괄호 추가)시켜야 하는 것이다. 추상 메서드가 하나라도 포함되어 있으면 추상 클래스가 되기 때문이고 구현시키지 않으면 문법 오류가 발생할 수 있다. 

 

또 주의해야 할 점이 있는데 바로 클래스에서의 메서드의 접근 지정자의 범위다.

인터페이스의 필드, 메서드의 접근 지정자는 명시하지 않아도 public abstracr 지정자가 붙기 때문에 이를 일반 클래스의 default 지정자와 헷갈리면 안된다. 하지만 사실상 인터페이스를 상속받는다면 자식 클래스의 구현 메서드 지정자는 public이 될 것이다.

 

 

· 인터페이스 객체 생성

인터페이스를 상속받는다는 의미 하에 추상클래스의 객체 생성법과 동일하다. 자식클래스나 익명 이너 클래스를 이용하면 된다.

 

 

· default 메서드와 static 메서드

인터페이스 내 완성 메서드가 올 수 있다. 

 

· 디폴트 메서드)

리턴타입 앞에 public default를 붙여 표기. 자식 클래스에서 오버라이딩할 의무가 없지만 오버라이딩이 가능하다. 하지만 인터페이스 자체가 객체를 여전히 생성할 수 없기 때문에 완성 메서드라 할지라도 일단 상속이 필요하다.

 

 

· 자식 클래스에서 부모 인터페이스의 디폴트 메서드 호출 방법

부모 인터페이스명.super.디폴트 메서드명

예를 들어 super.abc();으로 호출하면 상위 클래스인 Object 클래스 내부에서 abc명의 메서드를 찾는다.

따라서 부모 클래스의 abc() 메서드가 먼저 호출되고 나중에 자식 클래스의 abc() 메서드가 호출될 것이다.

부모 인터페이스명을 붙이는 이유는 인터페이스의 다중 상속 기능때문으로 , 어떤 부모 인터페이스인지 구분하기 위함이다.

 

 

· static 메서드)

객체를 생성하지 않고 바로 호출

 

문법)

인터페이스명.정적 메서드명();

 

반응형