(JAVA) 추상화
이번에는 추상화에 대해서 알아볼 것이다.
추상화라는 단어를 생각해보자 뭔가 애매한 느낌인가 싶지 않은가? 사실 그렇다.
추상화는 부모가 구현을 하지 않고, 부모가 이런게 있어..선언부만 작성하고 자식에게 던진다 (이번에는 가난한 상속인가 ㅠㅠ)
이렇게만 말하면 뭔 말인지 모를것이다. 이럴때는 코드와 설명이 최고지! (바로 아래 설명으로 가자)
abstract class buy{
abstract void fruit(int f1, int f2);
abstract void confectionery (int c1,int c2);
abstract void gohome();
}
class person1 extends buy{
@Override
public void fruit(int f1, int f2) {
System.out.printf("철수가 사과를 %d개 담았습니다. 바나나를 %d개 담았습니다.",f1,f2);
System.out.println("");
}
public void gohome(){
System.out.println("서울로 돌아갑니다");
}
@Override
public void confectionery(int c1, int c2) {
System.out.printf("쿠키를 %d개 담았습니다. 도리토스를 %d개 담았습니다.\n",c1,c2);
}
}
class person2 extends buy{ //만약 하나라도 구현 안하면 에러뜬다 그러면 abstract 붙이면 되는데 그럼 객체 못만든다.
public void fruit(int f1, int f2){}
public void gohome(){
System.out.println("인천으로 돌아갑니다.");
}
@Override
public void confectionery(int c1, int c2) {
System.out.printf("영희도 쿠키를 %d개 담았습니다. 도리토스를 %d개 담았습니다.\n",c1,c2);
}
}
public class Main {
public static void main(String[] args) {
person1 p1 = new person1();
p1.fruit(5, 6);
p1.confectionery(3, 4);
p1.gohome();
buy p2 = new person2(); //다형성 나중에 설명
p2.confectionery(1,2);
p2.gohome();
}
}
우선 출력은 아래와 같다.
철수가 사과를 5개 담았습니다. 바나나를 6개 담았습니다.
쿠키를 3개 담았습니다. 도리토스를 4개 담았습니다.
서울로 돌아갑니다
영희도 쿠키를 1개 담았습니다. 도리토스를 2개 담았습니다.
인천으로 돌아갑니다.
코드를 보면...
abstract class buy{
abstract void fruit(int f1, int f2);
abstract void confectionery (int c1,int c2);
abstract void gohome();
}
오잉 클래스와 메서드 앞에 abstract가 붙어 있다. 이게 추상화를 선언하는 방법이다. 그리고 앞서 말했듯 구현부인 {}가 안보인다 부모는 선언만 한다... 이렇게만 보면 간단한데 문제는 숨겨진 기능들이다.
class person1 extends buy{
@Override
public void fruit(int f1, int f2) {
System.out.printf("철수가 사과를 %d개 담았습니다. 바나나를 %d개 담았습니다.",f1,f2);
System.out.println("");
}
public void gohome(){
System.out.println("서울로 돌아갑니다");
}
@Override
public void confectionery(int c1, int c2) {
System.out.printf("쿠키를 %d개 담았습니다. 도리토스를 %d개 담았습니다.\n",c1,c2);
}
}
코드를 보면 부모가 해야할 구현부{}를 자식이 오버라이딩으로 채워넣는것이 보이는가? 이렇게만 보면 뭔가 비효율적인데... 왜...그...부모가 싹 다 한번만 정의한 다음에 자식이 쓰면 좋잖아?
class person2 extends buy{ //만약 하나라도 구현 안하면 에러뜬다 그러면 abstract 붙이면 되는데 그럼 객체 못만든다.
public void fruit(int f1, int f2){}
public void gohome(){
System.out.println("인천으로 돌아갑니다.");
}
@Override
public void confectionery(int c1, int c2) {
System.out.printf("영희도 쿠키를 %d개 담았습니다. 도리토스를 %d개 담았습니다.\n",c1,c2);
}
}
오... 다른 자식을 보니 이놈도 오버라이딩으로 메서드를 바꾸고 있다. 가만 생각해보니 부모가 아무것도 안하니깐 자식들이 각자 알아서 필요한 환경에 맞게 살아 남고 있다.
그렇다. 추상화를 쓰는 이유는 자식들이 알아서 입맛에 맞게 메서드를 고쳐쓰는데에 의미가 있다. 미완성 설계도라서(추상화 클래스) 상속 받고 상황에 맞게 고쳐 쓰기만 하면 되어서 관리가 용의하다.
또한 위에 주석에서 보이듯 추상화 부모를 상속 받았을때 부모가 준 매서드들을 전부 안쓰게 되면 바로 에러떠 버린다. 그리고 자바 개발자가 추상화 클래스는 객체를 못만들게 만들었다.
그래서 추상화는 메서드 사용을 강제하게 하는 기능도 있는 것이다. (abstract 보면 자식들이 이거 각각 다르게 구현부를 만들어서 무조건 써야해! 안쓰면 바로 에러로 혼내준다) 이런 약속이다.