객체 지향 프로그래밍
- 객체 지향 프로그래밍의 특징
- 정보 은닉
- 상속
- 다형성
다형성(Polymorphism)
하나의 메세지에 대해서 하위 클래스들이 서로 다르게 반응한다.
- 장점
- 메서드의 동작이 수정이 되더라도 부모의 메서드만 수정하면 된다.
- 확장이 용이하다.
- 부모의 메서드를 재정의 했다고 가정할 때, 부모를 통해서 자식의 메서드를 수행할 수 있다.
다형성의 올바른 예
public class Main {
public static void main(String[] args) {
Animal animal = new Dog();
animal.eat();
animal = new Cat();
animal.eat();
}
}
class Animal {
void eat() {
System.out.println("Eat");
}
}
class Dog extends Animal {
@Override
void eat() {
System.out.println("개처럼 먹다.");
}
}
class Cat extends Animal{
@Override
void eat() {
System.out.println("고양이처럼 먹다.");
}
}
다형성의 조건
- 상속관계
- Override(재정의)
- Upcasting(업캐스팅)
- 동적 바인딩
다형성 인자
다형성 인수를 활용하는 기본적인 방법은 아래와 같다.
자식 클래스의 종류에 따라서 다른 동작을 하도록 하기 위해서 여러 개의 메서드를 선언하는게 아니라 인자를 부모 클래스로 받아주면 된다.
이 때, Override된 메서드 이 외의 메서드를 사용하게 되면 에러
가 난다.
public class Main {
public static void main(String[] args) {
Dog d = new Dog();
Cat c = new Cat();
display(d);
display(c);
}
public static void display(Animal a) {
a.eat();
}
}
타입 검사와 캐스팅
다음과 같이 instanceof
연산자를 사용해서 타입 검사를 할 수 있고 true가 출력되는 경우에 대해서 DownCasting이 가능하다.
public static void display(Animal a) {
a.eat();
if(a instanceof Cat) {
((Cat) a).night();
}
}
다형성 배열
public static void main(String[] args) {
Animal[] animals = new Animal[2];
Cat cat = new Cat();
Dog dog = new Dog();
animals[0] = cat;
animals[1] = dog;
for(Animal animal: animals) {
animal.eat();
}
}
다형성의 보장
다형성을 보장한다 > 부모가 명령을 내리면 자식이 반드시 동작을 해야 한다 > 반드시 재정의가 되어야 한다
다형성에서 자식이 반드시 동작을 한다는 의미는 자식만의 메서드로 동작을 해야 한다는 것을 의미한다.
Abstract 다형성
메서드를 abstract로 만들게 되면 반드시 Override 해줘야 사용할 수 있다.
abstract class Animal {
abstract void eat();
}
class Dog extends Animal {
@Override
public void eat() {
}
}
class Cat extends Animal{
@Override
public void eat() {
}
}
Interface의 다형성
abstarct는 구현 메서드가 들어갈 수 있는데 이는 다음과 같은 문제를 불러올 수 있다.
- 구현체의 메서드가 상속받은 특정한 클래스에서는 사용되지 않는 경우
- 만약 상속 받은 객체에서 추상 클래스의 필드에 직접 접근할 수 있게 되면 이는 캡슐화를 깨트리는 것이다.
- 구현 메서드가 클래스가 동작하는데 있어서 아주 중요한 기능을 하는 경우 (예를 들면 템플릿 메서드 패턴)
이러한 문제를 막고자 구현체를 가질 수 없는 class 인 Interface를 고안했다.
public interface Remocon {
void chUp();
void chDown();
void volUp();
void volDown();
// 에러러 발생
// public void internet() {
// System.out.println("인터넷이 구동된다.");
// }
}
// abstract와 다르게 implements를 사용한다.
// 다중 상속(구현)이 가능하다.
class Radio implements Remocon {
@Override
public void chUp() {
System.out.println("라디오 채널이 올라간다.");
}
@Override
public void chDown() {
System.out.println("라디오 채널이 내려간다.");
}
@Override
public void volUp() {
System.out.println("라디오 볼륨이 올라간다.");
}
@Override
public void volDown() {
System.out.println("라디오 채널이 내려간다.");
}
}
class TV implements Remocon {
@Override
public void chUp() {
System.out.println("TV 채널이 올라간다.");
}
@Override
public void chDown() {
System.out.println("TV 채널이 내려간다.");
}
@Override
public void volUp() {
System.out.println("TV 볼륨이 올라간다.");
}
@Override
public void volDown() {
System.out.println("TV 채널이 올라간다.");
}
}