Java Syntax - (12) 추상클래스&인터페이스

가빈·2023년 12월 17일
post-thumbnail

클래스와 인터페이스는 공존할 수 없다. 클래스는 인터페이스 특성이 있고 인터페이스도 클래스의 특성이 있기 때문이다
클래스는 일반클래스와 추상클래스로 나뉘어진다
일반 클래스는 객체생성이 가능하고, 추상클래스는 객체 생성이 불가능하다

각각 어떤 경우에 써야하는지 판단할 줄 알아야한다

abstract class

추상클래스는 기계부품, 일반클래스는 기계틀이라고 생각하자

: 추상 메서드1개라도 있는 클래스
추상메서드 : abstract void abc();

  • ❗️객체 생성 불가 = 힙메모리가 아닌 스택 메모리에 저장되고 강제초기화값이 없어서 미완성인 상태가 된다

  • ⭐️ 추상 클래스를 상속받은 자식 클래스는 상속받은 추상메서드를 사용(오버라이딩)해야 오류가 나지 않는다

  • 추상 메서드가 하나라도 없을 때도 추상클래스로 정의는 가능하지만 그렇게 해야할 이유는 없음

오버라이딩 vs 구현하기

오버라이딩(overriding)
: 부모클래스의 메서드를 자식이 상속받아 재정의하는 것
->미완성/완성메서드 상관없음

구현하기(implements)
: 부모클래스의 미완성 메서드(추상메서드)를 자식클래스에서 재정의를 통해 완성시키는 것

❗️완성과 미완성의 구분은 중괄호의 존재여부

추상클래스를 이용한 객체 생성

방법 1) 추상클래스를 일반클래스로 상속해서 객체생성(클래스 수동생성)

abstract class A {
	abstract void abc();//미완성메서드
}
class B extends A {
	void abc() {
    ....... //완성된 메서드로 구현해서 객체생성가능
    }
}

A a = new B();
B b = new B();

방법 2) 익명이너클래스 사용(클래스 자동생성)

abstract class A {
	abstract void abc();//미완성메서드
}
A a = new A() { //객체 내에서 메서드를 완성시킨다
	void abc() {
    ... //클래스를 지정하지 않는 상태로 메서드를 완성시키면 컴파일러가 클래스를 자동 생성해줌
    }
}


interface

: 모든 메서드가 abstract이고 모든 필드가 static final, 모든 접근지정자가 public을 다 만족하면 인터페이스로 정의한다

  • 추상클래스와 똑같이 객체생성 불가
  • 필드 메서드 접근지정자 생략해도 자동으로 추가함

인터페이스의 상속

  • 상속 시, 구현하기 implements 사용
  • ⭐️다중상속 가능 = 부모가 여러 명 -> static으로 인해 모호성문제가 발생하지 않는다
  • 클래스와 교차로 상속가능(클래스 상속 후 구현하기 가능)
interface A {
	abstract abc();
}
class B implements A {
//구현 전이므로 오류 발생
//class는 완성된 메서드가 있어야 하기 때문이다
}
class B implements A {
	public void abc() {
    //이런식으로 완성시켜야한다. 
}
}

자주 실수하는 부분

interface A {
	void abc();
}
class B implements A {
	void abc() {
    ....
//완성해도 오류가 난다
/*class 내에서 접근지정자를 설정 안하면 default가 된다
public이라고 지정해줘야 오류가 안 난다*/
    }
}

상속 키워드

클래스 - 클래스 or 인터페이스 - 인터페이스 : extends
클래스 - 인터페이스 : implements

인터페이스 - 클래스 : 불가능
-> 인터페이스는 추상클래스이면서 static final 필드이면서 public이어야 하는데 그렇지 않는 것들도 상속받게 된다(완성-> 미완성)

인터페이스를 이용한 객체생성

추상클래스와 똑.같.다
방법 1) 인터페이스르르 일반 클래스로 상속해서 객체생성 (객체를 여러개 만들 때 유리)
방법 2) 익명이너클래스 사용(객체를 하나만 만들 때 유리)

디폴트 메서드

: 인터페이스 내부에서 완성된 메서드

  • 기존 인터페이스에 새로운 기능의 메서드를 추가할 경우, 구현헀던 클래스들이 새로운 메서드의 구현이 없으므로 오류가 발생한다 -> 디폴트메서드가 생겼다
  • 오버라이딩 가능
interface A {
	void abc();
    default void bcd() {
    	System.out.println("A 인터페이스의 bcd");
    }
//추상메서드만 구현
class B implements A {
	@Override
    public void abc() {
    	System.out.println("B클래스의 abc()");
        //A클래스의 bcd와 B클래스에서 완성된 abc 두개의 메서드가 출력
    }
    
//추상메서드 구현 + 디폴더 메서드 오버라이드
class C implements A {
	@Override
    public void abc() {
    	System.out.println("B클래스의 abc()");
    	}
    public void bcd() {
    	System.out.println("C클래스의 bcd()");
    	}//bcd가 오버라이딩 되면서 2개가 출력된다
	}
	
}
}

자식클래스에서 디폴트메서드 호출방법

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

interface A {
    default void bcd() {
    	System.out.println("A 인터페이스의 bcd");
    }

class B implements A {
	@Override
    public void bcd() {
    A.super.bcd(); // 인터페이스의 디폴트메서드 호출
    	System.out.println("B클래스의 abc()");

인터페이스에서 static 메서드

: 디폴드 메서드처럼 완성된 메서드
클래스에서 정적메서드 사용과 동일하다(객체 생성없이 바로 접근 가능)

  • 다중 상속 가능
profile
지금부터 시작!

0개의 댓글