728x90
✏️ 개요
- 인터페이스
- 사용하는 클래스가 사용되는 클래스의 종류와 상관없는 독립적인 클래스가 된다.
- 인터페이스의 메서드는 반드시 구현해야 하는 강제성을 갖는다.
- 추상클래스
- 인터페이스의 역할도 하면서 클래스의 기능도 가지고 있는 자바의 돌연변이 같은 클래스이다.
- 다형성
- 객체가 한 개 이상의 자료형의 타입을 갖게되는 특성을 의미한다.
- 부모 자식 상속 관계에 있으면 부모 타입으로 자식 클래스 타입을 받아 초기화할 수 있다.
- 자바에선 대표적으로 Overloading, Overriding, UpCasting, DownCasting, Interface, 추상메서드, 추상클래스 방법이 모두 다형성에 속한다.
🔎 자료형 다형성
- 다형성의 핵심은 '타입 묶음'이다.
- 공통적인 상속 클래스의 특징을 이용해 각 자료형의 타입을 묶는 것.
- 만일 각 자식 클래스에서 특수한 전용 메서드를 사용해야 하면, 메서드 오버라이딩 혹은 다운캐스팅을 통해 메서드를 실행시키면 된다.
🔎 매개변수 다형성
- 다형성의 특성은 변수의 타입뿐만 아니라 인터페이스나 파라미터에서도 똑같이 적용된다.
🔎 메서드 다형성
- 메서드를 확장하거나 재정의하는 overloading/ overriding 도 메서드가 다형해지기때문에 자바의 다형성 특징 중 하나에 속한다고 볼 수 있다.
📌 인터페이스
- default 메서드
- 디폴트 메서드를 사용하면 실제 구현된 형태의 메서드를 가질 수 있다.
- 오버라이딩이 가능하다.
- static 메서드
- 인터페이스에 static 메서드를 구현하면 인터페이스명.static 메서드명 과 같이 사용하여 일반 클래스의 static method를 사용하는 것과 동일하게 사용할 수 있다.
- interface 상수
- 인터페이스에 정의한 상수는 public static final 이 자동으로 적용된다.
interface Predator {
String getFood();
default void printFood() {
System.out.printf("my food is %s\n", getFood());
}
int LEG_COUNT = 4; // 인터페이스 상수
static int speed() {
return LEG_COUNT * 30;
}
}
📌 추상클래스
abstract class Predator extends Animal {
abstract String getFood();
void printFood() { // default 를 제거한다.
System.out.printf("my food is %s\n", getFood());
}
static int LEG_COUNT = 4; // 추상 클래스의 상수는 static 선언이 필요하다.
static int speed() {
return LEG_COUNT * 30;
}
}
- 인터페이스에서 default 메서드로 사용했던 printFood가 추상 클래스의 실제 메서드에 해당된다.
- 추상 클래스는 인터페이스와 달리 일반 클래스처럼 객체변수, 생성자, private 메서드를 가질 수 있다.
📌 다형성
- 자식 클래스에 의해서 만들어진 객체는 언제나 부모 클래스의 자료형으로 사용할 수 있다.
- 하나의 객체가 여러 개의 자료형 타입을 가질 수 있는 것을 객체지향 세계에서는 다형성이라고 한다.
interface Predator {
String getFood();
default void printFood() {
System.out.printf("my food is %s\n", getFood());
}
int LEG_COUNT = 4; // 인터페이스 상수
static int speed() {
return LEG_COUNT * 30;
}
}
interface Barkable {
void bark();
}
interface BarkablePredator extends Predator, Barkable {
}
class Animal {
String name;
void setName(String name) {
this.name = name;
}
}
class Tiger extends Animal implements Predator, Barkable {
public String getFood() {
return "apple";
}
public void bark() {
System.out.println("어흥");
}
}
class Lion extends Animal implements BarkablePredator {
public String getFood() {
return "banana";
}
public void bark() {
System.out.println("으르렁");
}
}
class ZooKeeper {
void feed(Predator predator) {
System.out.println("feed " + predator.getFood());
}
}
class Bouncer {
void barkAnimal(Barkable animal) {
animal.bark();
}
}
public class Sample {
public static void main(String[] args) {
Tiger tiger = new Tiger();
Lion lion = new Lion();
Bouncer bouncer = new Bouncer();
bouncer.barkAnimal(tiger);
bouncer.barkAnimal(lion);
}
}
- Bouncer 클래스의 barkAnimal 메서드의 입력 자료형이 Barkable이라도 BarkablePredator를 구현한 lion 객체를 전달할 수 있다.
- 그 이유는 BarkablePredator는 Barkable 인터페이스를 상속받은 자식 인터페이스이기 때문이다.
- 즉, 자식 인터페이스로 생성한 객체의 자료형은 부모 인터페이스로 사용하는 것이 가능하다.
인용
728x90
'디자인 패턴 > OOP' 카테고리의 다른 글
OOP (0) | 2023.09.07 |
---|---|
OOP의 4가지 특징 (0) | 2023.06.09 |
SOLID (좋은 객체 지향 설계의 5가지 원칙) (0) | 2023.06.07 |