Cute Running Puppy

Language/[Java] 자바 완전 정복

4주차_12. 추상 클래스와 인터페이스

R.silver 2022. 2. 10. 21:07
반응형

추상 클래스

추상 클래스의 정의

메서드 본체가 완성되지 않은 미완성 메서드

- 메서드의 기능을 정의하는 중괄호 부분이 비어있다. 

- 중괄호가 없기 때문에 세미콜론으로 끝나야 한다. 

 

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

 

추상 메서드를 1개 이상 포함하고 있는 클래스는 반드시 추상 클래스로 정의되어야 한다. 

 

abstract class 클래스명 {
    //추상 메서드가 1개 이상 포함되어 있으면 된다. 없어도 된다.
}

 

// 미완성 메서드
abstract abc();

// 완성 메서드
void abc () {
}

추상 클래스의 특징 

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

(A a = new A(); 불가)

추상 클래스를 상속한 자식 클래스를 생성하면 그 자식 클래스로는 객체를 생성할 수 있다. 

생성된 객체 내부에는 부모 클래스의 추상 메서드가 구현되어 있을 것이다. 

추상 클래스를 상속하는 자식 클래스는 부모에게 상속받은 미완성 메서드를 반드시 오버라이딩(완성) 해야 한다. 

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

추상 클래스 자체로는 객체를 생성할 수 없고 자식 클래스를 사용하여 객체를 생성해야 한다. 

 

방법 1

추상 클래스를 일반 클래스로 상속해서 객체 생성 

 

abstract class A {
    abstract void abc(); 
}

class B extends A {
	void abc() {
    	...
    }
}

 

abstract class A {
	abstract void abc();
}

class B extends A {
	void abc();
    	System.out.println("방법 1");
    }
}

// main 함수
	A b1 = new B();
    A b2 = new B();
    
    b1.abc(); // 방법 1
    b2.abc(); // 방법 1

 

방법 2

익명 이너 클래스 사용 

 

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

컴파일러가 내부적으로 추상 클래스를 상속해 메서드 오버라이딩을 수행한 클래스를 생성하고, 그 클래스로 객체를 생성하는 방법 

 

여러 객체를 만들어야 하는 상황이면 자식 클래스를 직접 정의 - 첫 번째 방법

한 번만 만들어 사용할 객체라면 익명 이너 클래스 사용 - 두 번째 방법

 

abstract class A {
	abstract void abc();
}

// main
	A a1 = new A() {
    	void abc() {
        	System.out.println("방법 2"); // 객체를 생성할 때마다 오버라이딩 필요
        }
    }; // ; 잊지 않기

	A a2 = new A() {
    	void abc() {
        	System.out.println("방법 2");
        }
    };
    
    a1.abc(); // 방법 2
    a2.abc(); // 방법 2

 

인터페이스

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

static, default 메서드 이외의 모든 메서드는 public abstract로 정의된 객체 프로그래밍 요소이다. 

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

 

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

 

인터페이스에 사용되는 제어가가 확정되어있기에 제어자를 생략해도 자동으로 추가된다

인터페이스의 상속

클래스가 인터페이스를 상속할 때에는 implements 키워드를 사용한다. 

상속에서 인터페이스의 가장 큰 특징은 다중 상속이 가능하다는 것 (class는 절대 불가)

 

클래스명 implement 인터페이스명, ..., 인터페이스명 {
    ...
}

 

인터페이스에서는 충돌이 발생할 수 없기 때문에 다중 상속이 가능하다 

(모든 필드가 public static final로 정의)

 

// 클래스와 인터페이스를 동시에 상속할 경우
클래스명 extends 클래스명 implement 인터페이스명, ..., 인터페이스명 {
    ...
}

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

// 1. 인터페이스를 일반 클래스로 상속해 객체 생성 
interface A {
	int a = 3;
    void abc();
}

class B implements A {
	public void abc() {
    	...
    }
}


// 2. 익명 이너 클래스 사용
A a = new A() {
	public void abc() {
    	...
    }
};

 

인터페이스의 필요성 

상속 관계가 아닌 클래스에 기능을 제공할 때 사용한다. 

하드워드를 예시로 들자면

하드웨어를 바꿀 때마다 새롭게 애플리케이션을 수정하지 않도록 하는 것이 인터페이스이다. 

디폴트 메서드와 정적 메서드 

 

interface 인터페이스명 {
    public default 리턴_타입 메서드명 {
        ...
    }
}

 

인터페이스 내부에 완성된 메서드를 삽입하는 것 

이미 완성된 메서드이므로 자식 클래스는 반드시 이 메서드를 오버라이딩 할 의무가 없다.

 

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

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

//인터페이스 내의 정적 메서드 호출

인터페이스명.정적_메서드

 

 

 

반응형