
클래스와 인터페이스는 공존할 수 없다. 클래스는 인터페이스 특성이 있고 인터페이스도 클래스의 특성이 있기 때문이다
클래스는 일반클래스와 추상클래스로 나뉘어진다
일반 클래스는 객체생성이 가능하고, 추상클래스는 객체 생성이 불가능하다
각각 어떤 경우에 써야하는지 판단할 줄 알아야한다
추상클래스는 기계부품, 일반클래스는 기계틀이라고 생각하자
: 추상 메서드가 1개라도 있는 클래스
추상메서드 : abstract void abc();
❗️객체 생성 불가 = 힙메모리가 아닌 스택 메모리에 저장되고 강제초기화값이 없어서 미완성인 상태가 된다
⭐️ 추상 클래스를 상속받은 자식 클래스는 상속받은 추상메서드를 사용(오버라이딩)해야 오류가 나지 않는다
추상 메서드가 하나라도 없을 때도 추상클래스로 정의는 가능하지만 그렇게 해야할 이유는 없음
오버라이딩(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() {
... //클래스를 지정하지 않는 상태로 메서드를 완성시키면 컴파일러가 클래스를 자동 생성해줌
}
}
: 모든 메서드가 abstract이고 모든 필드가 static final, 모든 접근지정자가 public을 다 만족하면 인터페이스로 정의한다
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()");
: 디폴드 메서드처럼 완성된 메서드
클래스에서 정적메서드 사용과 동일하다(객체 생성없이 바로 접근 가능)