RussellHouse
[Java] 23. Abstract 본문
Abstract
"이러한 내용들을 포함하도록 강제하시오."
그렇다면, java에서 특정 내용의 상속을 강제하는 방법은 없을까?
이러한 경우, 추상 메소드(Abstract)를 이용하면 된다. 이는 클래스나 메소드를 사용하기 위해서,
반드시 특정 사항을 사용하도록 강제하는 것을 의미한다.
추상 메소드란 메소드의 시그니쳐만이 정의된 비어있는 메소드를 의미한다.
아래의 예시를 보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | package org.opentutorials.javatutorials.abstractclass.example1; abstract class A{ public abstract int b(); //본체가 있는 메소드는 abstract 키워드를 가질 수 없다. //public abstract int c(){System.out.println("Hello")} //추상 클래스 내에는 추상 메소드가 아닌 메소드가 존재 할 수 있다. public void d(){ System.out.println( "world" ); } } public class AbstractDemo { public static void main(String[] args) { A obj = new A(); } } |
메소드 b의 선언 부분에는 abstract라는 키워드가 등장하고 있는데,
이 키워드는 메소드 b는 메소드의 시그니처만이 정의 되어 있고,
이 메소드의 구체적인 구현은 하위 클래스에서 반드시 오버라이딩 해야 함을 의미한다.
이와 같이 내용이 비어있는 메소드를 추상 메소드라고 부른다.
또한, 추상 메소드를 하나라도 포함하고 있는 클래스는 클래스의 이름 앞에
abstract가 붙는 '추상 클래스'가 된다.
=> "구체적인 내용이 이미 하달된 메소드의 경우에는 abstract를 붙일 수 없다."
1 2 3 | abstract class A{ public abstract int b(); } |
아래의 코드는 오류를 발생시키는데, 이는 내용이 비어 있는 추상 메소드를 실행시켰기 때문이다.
1 | public abstract int c(){System.out.println( "Hello" )} |
유의해야 할 점은, 추상 클래스에는 반드시 하나 이상의 추상 메소드가 존재하지만,
그렇지 않은 메소드 또한 존재할 수 있다는 것이다.
또 다른 유의해야 할 점은, 추상 클래스의 경우, 인스턴스화를 할 수 없다는 것이다.
이는 구체적인 메소드의 내용이 존재하지 않기 때문이다. => 강제 상속을 구현한 하위 클래스를 만든 후, 인스턴스 생성.
1 | A obj = new A(); |
위의 문제들을 해결하기 위해서는
우선 클래스 A를 상속한 하위 클래스를 만들고,
추상 메소드를 오버라이드해서 내용있는 메소드를 만들어야한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | package org.opentutorials.javatutorials.abstractclass.example2; abstract class A{ public abstract int b(); public void d(){ System.out.println( "world" ); } } class B extends A{ public int b(){ return 1 ;} } public class AbstractDemo { public static void main(String[] args) { B obj = new B(); System.out.println(obj.b()); } } |
위와 같이 하위 클래스인 B를 클래스 A를 상속하도록 정의하여 주고,
클래스 A의 추상 메소드인 메소드 b를 오버라이딩 하고 있다.
그 결과, 오류없이 클래스 A를 사용할 수 있었다.
추상 클래스는 상속을 강제하기 위한 것이다.
즉 부모 클래스에는 메소드의 시그니처만 정의해놓고
그 메소드의 실제 동작 방법은 이 메소드를 상속 받은 하위 클래스의 책임으로 위임하고 있다.
예제를 통해서 추상 클래스의 용도를 생각해보자.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package org.opentutorials.javatutorials.abstractclass.example3; abstract class Calculator{ int left, right; public void setOprands( int left, int right){ this .left = left; this .right = right; } public abstract void sum(); public abstract void avg(); public void run(){ sum(); avg(); } } class CalculatorDecoPlus extends Calculator { public void sum(){ System.out.println( "+ sum :" +( this .left+ this .right)); } public void avg(){ System.out.println( "+ avg :" +( this .left+ this .right)/ 2 ); } } class CalculatorDecoMinus extends Calculator { public void sum(){ System.out.println( "- sum :" +( this .left+ this .right)); } public void avg(){ System.out.println( "- avg :" +( this .left+ this .right)/ 2 ); } } public class CalculatorDemo { public static void main(String[] args) { CalculatorDecoPlus c1 = new CalculatorDecoPlus(); c1.setOprands( 10 , 20 ); c1.run(); CalculatorDecoMinus c2 = new CalculatorDecoMinus(); c2.setOprands( 10 , 20 ); c2.run(); } } |
위의 예제는 합계(sum)를 실행하고 평균(avg)을 실행하는 절차를
메소드 run을 통해서 한 번에 실행되도록 한 코드이다.
그런데 경우에 따라서 합계와 평균을 화면에 출력하는 모습을 달리해야 하는 경우가 있다고 치자.
그런 경우에 상황에 따라서 동작 방법이 달라지는 메소드(sum, avg)는 추상 메소드로 만들어서
하위 클래스에서 구현하도록 하고
모든 클래스의 공통분모(setOprands, run)의 경우에는
상위 클래스에 두어서 코드의 중복, 유지보수의 편의성 등을 꾀할 수 있다.
디자인 패턴
이러한 개발 방법을 template method pattern이라고도 한다. 아래는 추억의 템플릿이다.
위의 그림에 등장하는 템플릿은 자주 사용하는 모양을 모아둔 것이라고 할 수 있다.
템플릿은 모양을 결정하지만 템플릿을 통해서 그려질 도형은 팬의 종류나 색상에 따라서 달라진다.
즉 공통분모인 메소드 run은 메소드 sum과 avg가 어떻게 동작할지 알 수 없지만
sum이 실행되고 avg을 실행시킨다. 반면에 실행결과를 어떤 기호(+,-)로 시작할지는
하위 클래스에서 결정하고 있다.
즉, 위의 예제를 통해서도 알 수 있지만 프로그래밍이라는 것은 반복되는 패턴이 있다.
이런 패턴들을 모아서 정리한 것이 디자인 패턴(design pattern)이다.
물론 시각 디자이너들의 디자인이 아니라 좋은 소프트웨어를 만들기 위한 설계로서
디자인이라는 표현을 쓰고 있는 것이다. 디자인 패턴의 장점은 크게 두가지이다.
하나는 좋은 설계를 단기간에 학습할 수 있다는 점이다. 물론 비교적 단기간이라는 뜻이다.
다른 하나는 소통에 도움이 된다는 점이다.
설계 방법을 토의하거나 전달할 때 설계 방법에 따라 적절한 이름이 있다면
상호간에 생각을 일치시키는 데 큰 도움이 될 것이다.
지금 당장 디자인 패턴이 필요하지는 않겠지만 이러한 것이 있다는 것은 기억해두자.
프로그래밍에 대한 권태가 왔을 때 시작하기 딱 좋은 주제가 디자인 패턴이다.
'Java' 카테고리의 다른 글
[Java] 25. Interface (0) | 2017.12.23 |
---|---|
[Java] 24. Final (0) | 2017.12.23 |
[Java] 22. Access Controler (0) | 2017.12.23 |
[Java] 21. API&API document (0) | 2017.12.23 |
[Java] 20. Package (0) | 2017.12.22 |