1. 추상화
- 클래스 간 공통 속성을 찾아내서 공통 조상을 만드는 것
1-1. 추상화 예시 - 시작
public class Animal {
public void sound() {
System.out.println("동물 울음 소리");
}
}
public class Dog extends Animal {
@Override
public void sound() {
System.out.println("월월");
}
}
// Cat, Cow 클래스 구현 ...
- 개, 고양이, 소 ⇒ 실존 o
- 동물 ⇒ 추상적인 개념일 뿐, 실존 x
직접 인스턴스 생성(사용) 하지는 않음!! - 개, 고양이, 소 클래스에서 메서드 오버라이딩 하지 않으면 동물 클래스의 메서드가 실행됨
📌 위의 예시와 같이
1. Animal 인스턴스 생성할 수 있는 문제
2. 자식 클래스에서 메서드 오버라이딩 하지 않을 수 있는 문제
이러한 문제가 발생하지 않도록 제약 추가 ⇒ 추상 클래스, 추상 메서드 통해서!
1-2. 추상 클래스
- 부모 클래스는 제공하지만 실제 생성되면 안되는 클래스
- “미완성 설계도”
- 추상적인 개념 제공하는 클래스
- ⇒ 인스턴스 존재 x
- new 추상클래스(); 불가 : 인스턴스 생성할 수 없음!
- 상속 목적으로 사용됨, 부모 클래스 역할
- abstract 키워드 사용
abstract class AbstractAnimal { ... }
1-2-1. 추상 메서드
- 자식 클래스가 반드시 오버라이딩 해야 하는 메서드
- 자식 클래스가 추상 메서드를 오버라이딩 하지 않으면 자식 클래스도 추상 클래스가 되어야 함!
- abstract 키워드
- 메서드 바디 존재 x (선언만 해줌!)
- 나머지는 일반적인 메서드와 동일
// 추상 메서드 : 자체로는 호출 불가 => 자식 클래스에서 반드시 오버라이딩 해야 함
public abstract void abstractMethod();
📌 추상 메서드를 1개라도 갖는 클래스는 추상 클래스로 선언해야 한다!
1-2-2. 추상 클래스, 추상 메서드 예제
// 추상 클래스
public abstract class AbstractAnimal {
// 추상 메서드
public abstract void sound();
// 추상 메서드 x => 오버라이딩 여부 상관 x
public void move() {
System.out.println("동물 움직임");
}
}
public class Dog extends AbstractAnimal {
@Override
public void sound() {
System.out.println("월월");
}
}
// Cat, Cow 클래스 구현 ...
public static void main(String[] args) {
// 추상 클래스의 인스턴스 생성 불가!
// AbstractAnimal abstractAnimal = new AbstractAnimal();
}
📌 추상 클래스를 상속 받는 자식 클래스에서 메서드 오버라이딩을 하지 않으면
위의 그림과 같이 호출 불가 ⇒ 컴파일 오류 발생!
1-2-3. 순수 추상 클래스
- 클래스 내의 모든 메서드가 추상 메서드인 추상 클래스
public abstract class AbstractAnimal {
// 추상 메서드만 존재함 => 순수 추상 클래스
public abstract void sound();
public abstract void move();
}
- 자식 클래스는 반드시 모든 메서드를 오버라이딩 해야 함!
- 마치 규격 제시와 유사 ⇒ 인터페이스 같음 (USB 예시, USB 규격에 맞춰서 마우스, 키보드 등을 제작해야함)
- 순수 추상 클래스를 더 편리하게 사용하는 자바 기능 : 인터페이스임!
1-3. 인터페이스
- 순수 추상 클래스를 더 편리하게 사용하는 기능
- 클래스 x ⇒ interface 키워드
// 순수 추상 클래스
public abstract class AbstractAnimal {
public abstract void sound();
public abstract void move();
}
// 순수 추상 클래스를 인터페이스로 변경
public interface InterfaceAnimal {
public abstract void sound();
public abstract void move();
}
1-3-1. 인터페이스 특징
- 특징
- 순수 추상 클래스와 동일 (+ 편의기능 살짝 추가)
- 추가된 편의기능
- 인터페이스 내 모든 메서드는 public abstract 가 자동 추가됨 ⇒ 생략 권장
- 다중 구현 지원
- 인터페이스는 “구현” 하는 것 (상속 x)
인터페이스 : 물려받을 부모의 기능이 없고 구현해야 할 메서드만 존재
상속 : 부모 기능 물려받아서 사용하는 것이 목적
- 멤버 변수
- “인터페이스가 제공하는 상수”라고 생각
- 모든 멤버 변수는 public static final (생략 가능)
- 인터페이스는 빈 껍데기만 제공해야 함 ⇒ 멤버 변수는 상수만 가능!
public interface InterfaceAnimal {
// 멤버 변수 => 상수만 가능
public static final int PI = 3.14; // public static final 생략 가능
int ONE_HUNDRED = 100; // public static final 생략함
}
1-3-2. 인터페이스 구현
- implements 키워드
// 인터페이스
public interface InterfaceAnimal {
// public abstract : 생략 가능
(public abstract) void sound();
void move();
}
// 인터페이스 구현 클래스
public class Dog implements InterfaceAnimal {
@Override
public void sound() {
System.out.println("월월");
}
@Override
public void move() {
System.out.println("개 이동");
}
}
- 클래스 (상속)와 동일하게 new Dog() 로 인스턴스 생성 ⇒ 인스턴스에 InterfaceAnimal 또한 생성됨
📌 클래스, 추상 클래스, 인터페이스
모두 메모리 구조 상 똑같음!!
단지 제약이 추가될 뿐임
- 자바 8, 자바 9 변경 내용
더보기
자바 8 ⇒ default 접근제어자의 메서드 사용하면 인터페이스에서도 메서드 구현 가능 (예외적 경우에만 사용할 것!)
자바 9 ⇒ private 접근제어자의 메서드도 가능
1-4. 인터페이스와 다중 구현
- 인터페이스는 다중 구현이 가능함! (상속은 다중 상속 불가능)
- 인터페이스 2개 모두 methodCommon() 이라는 메서드를 가짐
- 상속 ⇒ 어떤 부모의 메서드 실행할지 결정해야 하는 다이아몬드 문제 발생
- 인터페이스 ⇒ 동일한 이름의 메서드지만 구현은 자식에서 함
+ 어차피 오버라이딩 해서 Child의 methodCommon()이 실행될 것임! - 따라서 다이아몬드 문제 x ⇒ 다중 구현 허용
public interface InterfaceA {
void methodA();
void methodCommon();
}
public interface InterfaceB {
void methodB();
void methodCommmon();
}
public class Child implements InterfaceA, InterfaceB {
@Override
public void methodA() {
System.out.println("Child.methodA");
}
@Override
public void methodB() {
System.out.println("Child.methodB");
}
@Override
public void methodCommon() {
System.out.println("Child.methodCommon");
}
}
⇒ methodCommon() 은 양쪽 인터페이스에 모두 존재하지만 Child에서는 같은 메서드이므로 1개만 구현!
public static void main(String[] args) {
InterfaceA a = new Child(); // 인터페이스도 다형적 참조 가능! ("부모는 자식을 담을 수 있다")
a.methodA();
a.methodCommon();
InterfaceB b = new Child();
b.methodB();
b.methodCommon();
}
/* 실행결과
Child.methodA
Child.methodCommon
Child.methodB
Child.methodCommon
*/
- methodCommon() 호출 시
1-5. 클래스와 인터페이스 활용
- 동시에 클래스 상속 + 인터페이스 구현 가능! (이때도 인터페이스 다중 구현 가능)
// Bird 클래스 예시만
public class Bird extends AbstractAnimal implements Fly {
@Override
public void sound() {
System.out.println("짹짹");
}
@Override
public void fly() {
System.out.println("새가 날아다님");
}
}
'Java' 카테고리의 다른 글
[Java] final (0) | 2024.07.09 |
---|---|
[Java] static (0) | 2024.07.09 |
[Java] 객체 지향 프로그래밍 - 다형성 (Polymorphism) (0) | 2024.07.09 |
[Java] 객체 지향 프로그래밍 - 상속 (Inheritance) (0) | 2024.07.08 |
[Java] 객체 지향 프로그래밍 - 캡슐화 (Encapsulation) (0) | 2024.07.08 |