오버로딩, 오버라이딩의 기본개념
오늘은 비슷하게 생긴 오버로딩(Overloading)과 오버라이딩(Overriding)의 차이점을 알아보겠습니다.
1.오버로딩(Overloading)
뭔가 배우기 전에 사전을 찾는 습관이 생겨버려서 찾아봤는데
Overloading은 "과적하다, 과부하" 이런 느낌에 뜻이군요...
사용해보면서 느껴보겠습니다
프로그래밍에서의 오버로딩을 한마디로 정의를 해보자면
"같은 클래스내에서 같은 이름의 메서드를 사용하는것"
한마디로 나타내보니 별거 없어보이네요 그대로 사용해보겠습니다.
사용해 보니 Duplicate method 어쩌구 뜨면서 에러가 나오네요 메서드가 똑같다 라고
에러를 띄어주네요. 생각해보면 당연한 에러입니다.. 구분할수가 없으니
오버로딩 사용에는 어쩔수 없이 조건이 붙게 됩니다.
① 매개변수 타입이 달라야 한다.
② 매개변수 개수가 달라야 한다.
2가지중 하나만 만족해도 사용이 가능해집니다. 조건에 맞춰서 사용해보겠습니다.
① 매개변수 타입이 달라야한다
② 매개변수 개수가 달라야한다
조건에 맞춰서 사용하니 동작이 잘 되네요.
사용법은 알았는데 왜 사용할까요? 좋은점이 있을까요?
실제로 개발을 하다보면 프로젝트가 커지고 여러사람과 공유하면서 개발하기 때문에
오버로딩을 사용하지 않으면 작성하는 사람이나 사용하는 사람이나 이름 짓기도 어렵고
알아보기도 힘이 들어서 효율성이 떨어집니다.
간단하게 더하기를 하려고 해도
오버로딩을 사용하면 void add(int a, int b ㆍㆍㆍ)
이렇게 편하게 add 하나만 외워두고 쓰면 되지만
오버로딩이 없다면 void add_two(int a, int b) void add_three(int a, int b, int c)
이렇게 복잡해 진답니다. 여기에서 int형 하나만이 아니고 float형까지
구분해서 더하려면 더 헷갈리겠죠??
사용해보니 오버로딩의 사전적 뜻을 얼추 맞춰보면 과적이 트럭한대에 계속 끊이없이
쌓는다는 뜻으로 생각하면 프로그래밍에서도 하나의 메서드이름으로 끝없이 사용할 수
있다는 의미가 아닐까 생각합니다.. 이 뜻이 아니면 어쩔수 없구요.
이상으로 마치고 오버로딩에 대해 더 알고 싶으신분들은 println()도 오버로딩이니
api doc 보셔도 되고, 직접 이클립스에서 뜯어보셔도 도움이 될 것 같습니다.
이클립스에서는 println() 하나 쓰시고 컨트롤 클릭하면 PrintStream.class가 열린답니다
사진 올리고 보니 저도 갑자기 분석하고 싶어지네요.
나중에 한번 println() 관련해서 글 올려보겠습니다.
-------------------------------------------------
이 부분은 몰라도 되는부분인데 실제로는 컴파일러가 컴파일과정에서
add(int a), add(int a, int b) 이렇게 들어가는것이 아니고
add(int a), add(int a, int b) --> add_a(int a), add_b(int a, int b)
이런식으로 변경을 해줍니다
2.오버라이딩(Overriding)
공부하기 전에 Overriding의 사전적 의미를 찾아보면
Override는 "무시하다, 무효하다, 기각하다" 이런 느낌이고
Overriding은 "가장 우선되는, 최우선되는, 다른것보다 우선인" 이런 느낌이네요
사용해보면서 알아보겠습니다.
프로그래밍에서의 오버라이딩을 한마디로 정의를 해보자면
"부모Class에서 정의한 메서드를 자식 Class에서 변경하는 것"
한마디로 나타냈는데 프로그래밍에 부모가 나오고 자식이 나오고 하네요.
저도 대학교 유닉스 수업때 교수님이 Parent-Child 관계 설명하면서 처음
알게 된 용어입니다.
오버라이딩을 알기위해선 먼저 상속이라는 것을 알아야 합니다.
현실에서 상속이라 함은 부모님이 물려주시는 재산상속이라던지 빚상속 이런거죠
프로그래밍에서도 비슷하다고 생각하시면 됩니다
예제를 하나 만들어봤는데 뭐 상속해도 부모가 계속 써도 상관없습니다.
자바의 객체지향의 목적이 현실세계를 컴퓨터안에서 비슷하게나마 구현하는 것이니..
한번 만들어봤습니다만 쉽지는 않네요 현실과 똑같이 구현하기가..
상속에 대해 알아봤으니 이제 위에서 정의한대로 오버라이딩을 사용해보겠습니다.
"부모Class에서 정의한 메서드를 자식 Class에서 변경하는 것"
정의한대로 자식 Class에서 내용을 변경했고, 결과를 확인하니 잘 변경됬습니다.
그런데 이걸 쓰는 이유가 뭘까요? 오버라이딩의 장점인 예제를 하나 보겠습니다.
햄버거가게를 예를 들겠습니다.
각 가격은 햄버거 : 2000원, 콜라 : 1000원, 감자튀김 : 500원 입니다
햄버거+콜라+감자튀김을 따로 주문하는 경우와, 셋트로 주문하는 경우를 보겠습니다
이처럼 자식 Class에서 내용을 변경해야 할 상황이 올 때 사용할 수 있습니다.
자식 Class에서 재정의가 이루워질때 이를 최우선으로 한다 해서 사전적의미에
Overriding을 사용하는 것 같습니다.
오버라이딩도 오버로딩과 마찬가지로 메서드의 이름을 하나로 사용함으로 인해서
개발 시 효율성을 높일 수 있습니다.
오버라이딩 사용시 알아둬야 할 것이 더 있습니다.
기본적인 조건인 메서드이름이 같아야한다던가 매개변수,
리턴타입이 같아야한다는건 제외시키겠습니다.(따로 설명 안해도 바로 아실듯)
그건 바로,
Static 메서드 오버라이딩을 허용하지 않는다.
이렇게만 아시고 넘어가셔도 됩니다만 이유가 궁금하신분들은 더 읽어주세요~
기본적으로 오버라이딩을 하려고 할 때 위에 그림처럼 자동완성이 뜨고 선택하면
위에처럼 자동으로 완성된다 여기서 @Override(Annotation 이라 합니다)
이 표시는 넣으나 안넣으나 결과는 같으나
개발자의 실수를 방지하기 위해 자바에서는 쓰는걸 권장합니다.
여기서 price를 static 메서드로 바꾸면 어떻게 될까요?
static 메서드로 바꾸니 에러가 뜹니다.
그런데 이 상황에서 @Override를 삭제하면 에러가 사라지고 프로그램이 돌아갑니다.
에러도 안뜨고 결과도 그대로 나왔고 문제가 없다고 생각 하실수 있습니다.
@Override를 삭제하는 경우가 아니여도 자동완성 기능을 안쓴다면 무심코
static 메서드를 오버라이딩 하는경우가 생기기도 합니다.
결과적으로 보면 위 statc void price() 메서드는 오버라이딩을 허용한 것이 아닙니다.
이것에 대해 100% 이해하려면 static, 메모리, 다형성등 이해해야 하므로 간단하게만
알아보겠습니다.
전에 올렸던글(static,JVM의 기본) 내용에도 있드시 static은 특별취급합니다.
인스턴스와 다르게 static 메서드는 정적메서드로 코드가 읽히기 전에 미리
메모리상에 자리를 잡고 있습니다.(생성자 호출전에 미리 값이 결정)
static 메서드는 기본적으로 재정의가 되지 않지만 상속일 경우 자식 class에서
재정의를 할 수 있지만, 그 후에 부모 class에 접근했을 때 static 메서드가 숨는
현상이 일어나게 되는데 이를 하이딩(Hiding)이라 합니다
(하이딩이 오버라이딩의 기법이라는 얘기는 들었는데, static 메서드가
오버라이딩된다라고 말하기는 조금 어색한거 같습니다)
static 메서드로 오버라이딩하기 위해 @Override를 강제로 삭제하거나
실수로 사용하게 되서 프로그램이 돌아간다고 해도 결국
오버라이딩이 아니라 하이딩으로 처리가 된겁니다.
자바에서는 Static을 하이딩으로 사용하는것을 추천하지 않습니다.
JVM가 실행되면 실제 객체를 찾아 호출하는 과정이 진행되는데
인스턴스 메서드는 이에 포함이 되지만, static 메서드는 포함이 안됩니다.
예제를 통해서 차이점을 알아보고 끝내도록 하겠습니다.
출처: https://itpangpang.xyz/105 [ITPangPang]