육군, 공군, 해군이 나오는 K전투 게임개발을 하고 있던 개발자 A씨. 군인들은 모두 공격을 수행하니까 attack이라는 부모클래스의 메서드를 상속받아 오버라이드한 뒤 처리하는 것이 옳다고 우린 앞의 상속에서 배웠다. 하지만 A씨는 상속을 그냥 잊고 본인 마음대로 클래스의 메서드 이름을 att, attn, atta 이런식으로 지정하여 만들었다. 그리고 A씨는 몇달 뒤 자유를 찾은 도비가 되었고, 다른 개발자인 B씨가 입사하게 되었다.
A씨의 코드를 보니 B씨는 심란하다. 뭘 이렇게 해놓은거지? 메서드 이름들은 대체 뭘 뜻하는거지? 알수 없는 코드들을 보며 B씨는 유지보수 및 사이드 이펙트에 대해 심각하게 고민하게 된다.
개발자로 일한다는 것은 협업을 한다는 것이다. 나 혼자 만들어서 프로그램을 뚝딱 만들면 좋겠지만 이건 빌딩을 혼자서 공구리질 해가며 짓겠다는 것과 유사한 무모한 느낌을 준다. 혼자 만들땐 가독성따위 필요없다. 그냥 내 눈에만 잘 보이고, 내 머릿속에서만 잘 돌아가면 되는 것이다. 하지만 여러명과 함께 만들면 우린 규칙이 필요하다. 누가 봐도 읽기 쉽고(다형성), 유지보수(상속성)하기도 쉽게끔 코드를 짜는 것이 옳다는 말이다.
기획서를 쓸 때를 생각해보자. 부장님이 자유롭게 써와~ 라고 해서 진짜 자유롭게 써간 신입사원 A씨, 마인드맵도 그리고 보노보노 배경도 넣고 심각한 혼종을 만들어 왔다고 치자. 보고서를 받아든 부장님의 얼굴이 덩달아 심각해진다. 음... 진짜 자유롭게 써왔네? 하고 눈치를 주며 다시 써오라며 재지시를 받은 A씨는 대체 부장님이 원하는게 뭘까 궁금하고 답답해진다.
하지만 여기서 기획서 양식이 있다고 하면 어떨까? 구체적인 가이드라인이 있으니 A씨 입장에서도 채워넣기 한결 쉽고 부장님 입장에서도 내용이 적절하게 들어갔는지 체크할 수 있으니 일석이조다.
추상화는 가이드라인이다. 양식 자체에는 효력이 없지만 내용을 기입하면 효력이 생긴다. 양식에다가 데이터 값을 적어서 배부하는 경우는 없다. 추상화도 마찬가지다. 자체적으로 내용을 생성하는 것은 없이 양식만 준다고 보면 되겠다.
// 선언만 가능하고, 구현부를 위한 블록이 존재하지 않는다.
public abstract void sayHello();
// 추상 클래스 정의
public abstract class Hello {
// 선언만 가능하고, 구현부를 위한 블록이 존재하지 않는다.
public abstract void sayHello();
}
<실습 01>
public abstract class Unit {
private String name;
public Unit(String name) {
super();
this.name = name;
}
/** getter, setter */
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
// 자식들이 재정의할 메서드를 추상으로 명시
public abstract void attack();
public abstract void move();
}
/**
* 추상 클래스를 상속받으면 자식은 부모의 모든 추상 메서드를
* 재정의 해야 한다.
*/
public class Army extends Unit {
public Army(String name) {
super(name);
// TODO Auto-generated constructor stub
}
@Override
public void attack() {
System.out.println(this.getName() + " >> 육상공격");
}
@Override
public void move() {
System.out.println(this.getName() + " >> 육상이동");
}
}
public class Navy extends Unit {
public Navy(String name) {
super(name);
}
@Override
public void attack() {
System.out.println(this.getName() + " >> 해상공격");
}
@Override
public void move() {
System.out.println(this.getName() + " >> 해상이동");
}
}
public class AirForce extends Unit {
public AirForce(String name) {
super(name);
}
@Override
public void attack() {
System.out.println(this.getName() + " >> 공중공격");
}
@Override
public void move() {
System.out.println(this.getName() + " >> 공중이동");
}
}
public class Main01 {
public static void main(String[] args) {
Army army = new Army("육군");
Navy navy = new Navy("해군");
AirForce air = new AirForce("공군");
// 다형성이란, 객체의 이름이 서로 다르더라도 -
// 객체의 메서드를 호출할 때 고민하지 않기 위한 기법이다.
// 추상화는 다형성을 강제하는 것으로 -
// 객체를 사용하는 개발자의 편의를 위한 클래스 작성 규칙이다.
army.move();
army.attack();
navy.move();
navy.attack();
air.move();
air.attack();
}
}
이 포스트는 itpaper.co.kr에서 제공되는 강의자료를 바탕으로 작성되었습니다.