Java

abstract

abstract

abstract란 한국어로는 추상으로 번역된다. 이에 대한 정의는 뒤에서 내리도록 하고 지금 단계에서는 abstract라는 것이 상속을 강제하는 일종의 규제라고 생각하자. 즉 abstract 클래스나 메소드를 사용하기 위해서는 반드시 상속해서 사용하도록 강제하는 것이 abstract다. 

추상 메소드

추상 메소드란 메소드의 시그니처만이 정의된 비어있는 메소드를 의미한다. 아래의 코드를 보자.

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();
	}
}

위 코드의 실행 결과는 아래와 같다.

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
    Cannot instantiate the type A

	at org.opentutorials.javatutorials.abstractclass.example1.AbstractDemo.main(AbstractDemo.java:7)

 메소드 b의 선언 부분에는 abstract라는 키워드가 등장하고 있다. 이 키워드는 메소드 b는 메소드의 시그니처만 정의 되어 있고 이 메소드의 구체적인 구현은 하위 클래스에서 오버라이딩 해야 한다는 의미다. 이렇게 내용이 비어있는 메소드를 추상 메소드라고 부른다. 추상 메소드를 하나라도 포함하고 있는 클래스는 추상 클래스가 되고, 자연스럽게 클래스의 이름 앞에 abstract가 붙는다. 

abstract class A{
    public abstract int b();
}

아래 코드는 오류를 발생시키는데 본체인 {System.out.println("Hello")}가 존재하는데 추상 메소드를 의미하는 abstract를 사용하고 있기 때문이다.

public abstract int c(){System.out.println("Hello")}

추상 클래스에는 추상 메소드가 아닌 메소드가 존재할 수 있다.

public int d(){
	System.out.println("world");
}

아래와 같이 추상 클래스 A를 인스턴스화하면 오류가 발생한다. 그것은 추상 클래스는 구체적인 메소드의 내용이 존재하지 않기 때문에 인스턴스화시켜서 사용할 수 없기 때문이다. 그럼 어떻게 해야 클래스 A를 사용할 수 있을까? 또 이렇게 불편한 추상 클래스는 왜 사용하는 것일까?

A obj = new A();

추상 클래스의 상속

위의 문제를 해결하기 위해서는 클래스 A를 상속한 하위 클래스를 만들고 추상 메소드를 오버라이드해서 내용있는 메소드를 만들어야 한다. 아래 코드를 보자.

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를 사용할 수 있었다.

추상 클래스를 사용하는 이유

추상 클래스는 상속을 강제하기 위한 것이다. 즉 부모 클래스에는 메소드의 시그니처만 정의해놓고 그 메소드의 실제 동작 방법은 이 메소드를 상속 받은 하위 클래스의 책임으로 위임하고 있다. 사실 코드를 이런 식으로 작성하는 경우는 작은 규모의 프로젝트에서는 거의 없다. 예제를 통해서 추상 클래스의 용도를 생각해보자.

아래 코드는 계산기 예제에 추상 클래스의 개념을 도입한 것이다.

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 :30
+ avg :15
- sum :30
- avg :15

위의 예제는 합계(sum)를 실행하고 평균(avg)을 실행하는 절차를 메소드 run을 통해서 한 번에 실행되도록 한 코드이다. 그런데 경우에 따라서 합계와 평균을 화면에 출력하는 모습을 달리해야 하는 경우가 있다고 치자. 그런 경우에 상황에 따라서 동작 방법이 달라지는 메소드(sum, avg)는 추상 메소드로 만들어서 하위 클래스에서 구현하도록 하고 모든 클래스의 공통분모(setOprands, run)의 경우에는 상위 클래스에 두어서 코드의 중복, 유지보수의 편의성 등을 꾀할 수 있다.

디자인 패턴

 

지금 단계에서는 난이도가 있으면서 부가적인 내용이다. 다음 내용은 부담 없이 보자.

이러한 개발 방법을 template method pattern이라고도 한다. 아래는 추억의 템플릿이다.

위의 그림에 등장하는 템플릿은 자주 사용하는 모양을 모아둔 것이라고 할 수 있다. 템플릿은 모양을 결정하지만 템플릿을 통해서 그려질 도형은 팬의 종류나 색상에 따라서 달라진다. 즉 공통분모인 메소드 run은 메소드 sum과 avg가 어떻게 동작할지 알 수 없지만 sum이 실행되고 avg을 실행시킨다. 반면에 실행결과를 어떤 기호(+,-)로 시작할지는 하위 클래스에서 결정하고 있다.

즉, 위의 예제를 통해서도 알 수 있지만 프로그래밍이라는 것은 반복되는 패턴이 있다. 이런 패턴들을 모아서 정리한 것이 디자인 패턴(design pattern)이다. 물론 시각 디자이너들의 디자인이 아니라 좋은 소프트웨어를 만들기 위한 설계로서 디자인이라는 표현을 쓰고 있는 것이다. 디자인 패턴의 장점은 크게 두가지이다. 하나는 좋은 설계를 단기간에 학습할 수 있다는 점이다. 물론 비교적 단기간이라는 뜻이다. 다른 하나는 소통에 도움이 된다는 점이다. 설계 방법을 토의하거나 전달할 때 설계 방법에 따라 적절한 이름이 있다면 상호간에 생각을 일치시키는 데 큰 도움이 될 것이다.

지금 당장 디자인 패턴이 필요하지는 않겠지만 이러한 것이 있다는 것은 기억해두자. 프로그래밍에 대한 권태가 왔을 때 시작하기 딱 좋은 주제가 디자인 패턴이다.

댓글

댓글 본문
  1. nextLevel
  2. wwwqiqi
    완료... 더 좋은 개발자가 되기위해선 디자인패턴도 제대로 공부해야겠네요 감사합니다.
  3. infernist
    2022/10/31
  4. Alan Turing
    09/09
  5. PassionOfStudy
    복습 4일차!
  6. 김은희
    20220615 완료 헷갈린다좀ㅍ다시보기
  7. PassionOfStudy
    abstract! 디자인패턴! template method pattern!
  8. dogchang
    22.05.05 1차 완료.
    abstract는 특정 메소드에 대해서 수많은 경우의 수를 전부 대비하여 개발할수 없으므로 추상적인 클래스와 그 안에 추상+일반 메소드를 선언하고 해당 클래스를 상속(extends)받아 상속받은 클래스에서 오버라이딩(overriding) 하여 사용하도록 하는 방법.

    정주행 완료후 2차 정주행때 다시 개념을 확인할 것.
  9. 자바잡아
    22.05.03 Final Attack Ride. Abstract!!!
  10. 20220427
  11. 모찌말랑카우
    22.02.17
  12. 민둥빈둥
    22.02.12
  13. aesop0207
    220208 Tue
  14. 행달
    22.02.06 완료!
  15. 드림보이
    2021.12.15. abstract 파트 수강완료
  16. syh712
    2021-12-09
    <abstract>
    1. bstract라는 것이 상속을 강제하는 일종의 규제. 즉 abstract 클래스나 메소드를 사용하기 위해서는 반드시 상속해서 사용하도록 강제하는 것이 abstract다.
    내용이 비어있는 메소드를 추상 메소드라 함.
    추상 메소드를 하나라도 포함하고 있는 클래스는 추상 클래스가 됨.
    abstract class A{
    public abstract int b();
    public void d(){
    System.out.println("world");
    }
    }
    class B extends A{
    public int b(){return 1;}
    }

    => 클래스 B는 클래스 A를 상속. 클래스 A의 추상 메소드인 메소드 b를 오버라이딩하고 있다. 그 결과 클래스 A를 사용할 수 있음.

    2. 추상 클래스를 사용하는 이유
    상황에 따라서 동작 방법이 달라지는 메소드(sum, avg)는 추상 메소드로 만들어서 하위 클래스에서 구현하도록 함.
    모든 클래스의 공통분모(setOprands, run)의 경우에는 상위 클래스에 두어서 코드의 중복, 유지보수의 편의성 등을 꾀할 수 있다.


    3, 디자인 패턴
    프로그래밍이라는 것은 반복되는 패턴이 있다. 이런 패턴들을 모아서 정리한 것이 디자인 패턴(design pattern)이다.
    디자인 패턴의 장점은 크게 두가지이다. 하나는 좋은 설계를 단기간에 학습할 수 있다는 점이다.
    다른 하나는 소통에 도움이 된다는 점이다. 설계 방법을 토의하거나 전달할 때 설계 방법에 따라 적절한 이름이 있다면 상호간에 생각을 일치시키는 데 큰 도움이 될 것
  17. H4PPY
    1102
  18. IaaS
    2021.11.02 수강완료
  19. super1Nova
    210830
  20. 베이스박
    210826 학습완료
  21. Eunyoung Eunice Kang
    2021.8.16(월) 완료
  22. 악어수장
    2021-5-10 완료
  23. 김태현
    //본체가 있는 메소드는 abstract 키워드를 가질 수 없다.
    //public abstract int c(){System.out.println("Hello")}
    //추상 클래스 내에는 추상 메소드가 아닌 메소드가 존재 할 수 있다.
  24. 김태현
    abstract는 상속해야먄 사용가능
    abstract 클래스에는 주제(대메뉴)

    상속 클래스는
    소주제로 디테일한 코드 구현



    abstract를
    생성자로 불러다가 쓸 수 없다.

    반듯이 상속을 받아서 생성자등을 사용해서 쓸 수 있다.
  25. EunSeok Kang
    잘보고 갑니다. 감사합니다. 20200813
  26. hvii
    20200812
  27. 김요한
    2020.07.31
    7월의 마지막 날... 3주 정도만에 겨우 여기까지 왔네요;;;
    배움과 다소 더딘 편이라 복습 위주로 하면서 진도는 더디게 나가고 있지만....
    항상 감사함을 느끼고 있습니다!

    남은 과목도 끝까지 이해하고 수료하겠습니다!
  28. 김승민
    2020-04-21
    감사합니다~
  29. 열심히공부하십쇼
    오호 몇번 돌리니까 이해가 가네요
  30. aminora
    쉽게말하면 추상클래스라는건 관리요원(설계자)의 지침사항이고
    이 지침사항을 토대로 각자 다른 무대에서 실제로 일하는 무대1실행요원(클래스1), 무대2실행요원(클래스2)
    를 설정해놓는거라고 이해하면 될듯하네요 ㅎ
  31. 없으면안돼요
    3번째 수강에서 이해가 가네요
  32. 크리스
    감사합닏.
  33. 허공
    감사합니다!
  34. PassionOfStudy
    191007(월) - (2)
    수강완료~
  35. 홍주호
    20190915 완료
  36. 하여진
    이해했습니다.
  37. 다나가
    190905 - 수강완료
  38. doevery
    수강완료
  39. proud00
    저는 추상클래스를 상속받아 사용하는 하위클래스를 각 언어별로 다르게 구현하는 것으로 상상해봤어요. 예를들면 하위클래스 하나는 영어로, 또 하나는 한국어로 나오도록 구현하는 식으로요.
  40. 소월
    디자인 패턴!!
  41. 6/17시작
    7월 3일 완료
  42. 데볼
    디자인 패턴이라는게 있는지 몰랏네요 알고갑니다.
  43. Jayce99
    이해가 쏙쏙 됩니다. 항상 감사합니다 :)
  44. 라또마니
    abstract , 그리고 디자인 패턴의 중요성.. 잘 배웠습니다.
  45. j-graphy
    2019. 02. 21. 학습완료
  46. 몰래온손님
    잘배우고 갑니다
  47. 기수니
    많은 도움이 되었습니다, 감사합니다.
  48. 한라봉
    완료
  49. 이준송
    나그네님의 의견에 더합니다.

    공동공구님의 질문의 요지는 왜 추상클래스가 굳이 필요한가입니다.

    저의 짧은 식견으로 이야기해보자면, 상황을 2개를 가지고 이야기하겠습니다.

    1. 추상클래스가 상위 클래스인 경우
    2. 일반적인 상위클래스인 경우

    1번의 경우 우리는 추상메소드라고해서 굳이 구현의 부담을 느낄 필요가 없습니다. 즉 어짜피 자식클래스에 따로 구현할 건데 껍데기만 불과한 최상위 클래스에 굳이 구현의 필요성이 있냐는 것이죠.

    반면, 2번 클래스의 경우 우리에게 나름의 구현의 부담감을 줍니다. 물론 [ } 이렇게 처리하셔서 구현 안하셔도 됩니다만..

    정리하자면, 추상클래스의 경우 abstract라는 선언으로써 이 함수는 껍데기에 불과하기때문에 구현의 부담감이 사라짐과 동시에, 앞으로 하위클래스로 쓰일 놈들은 이 추상메소드들을 변형하여서 쓰일 것이라는.. 전체적인 코드를 이해하는 데 작은 단서까지 주는 일석이조의 효과까지 있는 셈이죠.
    대화보기
    • 이태호
      7/11
      디자인 패턴